using SQLite;
using System.Linq.Expressions;
using salesbook.Shared.Core.Entity;

namespace salesbook.Maui.Core.Services;

public class LocalDbService
{
    private const string DB_NAME = "task_db.db3";
    private readonly SQLiteAsyncConnection _connection;

    public LocalDbService()
    {
        _connection = new SQLiteAsyncConnection(Path.Combine(FileSystem.AppDataDirectory, DB_NAME));

        _connection.CreateTableAsync<AnagClie>();
        _connection.CreateTableAsync<JtbComt>();
        _connection.CreateTableAsync<PtbPros>();
        _connection.CreateTableAsync<PtbProsRif>();
        _connection.CreateTableAsync<StbActivity>();
        _connection.CreateTableAsync<VtbCliePersRif>();
        _connection.CreateTableAsync<VtbDest>();
        _connection.CreateTableAsync<StbActivityResult>();
        _connection.CreateTableAsync<StbActivityType>();
        _connection.CreateTableAsync<SrlActivityTypeUser>();
        _connection.CreateTableAsync<StbUser>();
        _connection.CreateTableAsync<VtbTipi>();
        _connection.CreateTableAsync<Nazioni>();
    }

    public async Task ResetSettingsDb()
    {
        try
        {
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS stb_activity_result;");
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS stb_activity_type;");
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS srl_activity_type_user;");
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS stb_user;");
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS vtb_tipi;");
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS nazioni;");

            await _connection.CreateTableAsync<StbActivityResult>();
            await _connection.CreateTableAsync<StbActivityType>();
            await _connection.CreateTableAsync<SrlActivityTypeUser>();
            await _connection.CreateTableAsync<StbUser>();
            await _connection.CreateTableAsync<VtbTipi>();
            await _connection.CreateTableAsync<Nazioni>();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Errore durante il reset del database(settings): {ex.Message}");
            throw;
        }
    }

    public async Task ResetDb()
    {
        await ResetSettingsDb();

        try
        {
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS anag_clie;");
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS jtb_comt;");
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS ptb_pros;");
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS ptb_pros_rif;");
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS stb_activity;");
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS vtb_clie_pers_rif;");
            await _connection.ExecuteAsync("DROP TABLE IF EXISTS vtb_dest;");

            await _connection.CreateTableAsync<AnagClie>();
            await _connection.CreateTableAsync<JtbComt>();
            await _connection.CreateTableAsync<PtbPros>();
            await _connection.CreateTableAsync<PtbProsRif>();
            await _connection.CreateTableAsync<StbActivity>();
            await _connection.CreateTableAsync<VtbCliePersRif>();
            await _connection.CreateTableAsync<VtbDest>();

            Console.WriteLine("Database resettato con successo.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Errore durante il reset del database: {ex.Message}");
            throw;
        }
    }

    public Task InsertAll<T>(List<T> entityList) =>
        _connection.InsertAllAsync(entityList, typeof(T));

    public async Task Insert<T>(List<T> entityList)
    {
        foreach (var entity in entityList)
        {
            try
            {
                await _connection.InsertAsync(entity, typeof(T));
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Errore db su {entity}: {ex.Message}");
            }
        }
    }

    public async Task InsertOrUpdate<T>(List<T> entityList)
    {
        foreach (var entity in entityList)
        {
            var result = await _connection.UpdateAsync(entity);
            if (result == 0)
            {
                await _connection.InsertAsync(entity);
            }
        }
    }

    public Task<List<T>> Get<T>(Expression<Func<T, bool>>? whereCond = null) where T : new() =>
        whereCond is null
            ? _connection.Table<T>().ToListAsync()
            : _connection.Table<T>().Where(whereCond).ToListAsync();

    public List<T> Get<T>(string sql) where T : new() => _connection.QueryAsync<T>(sql).Result;

    public async Task Delete<T>(T entity) =>
        await _connection.DeleteAsync(entity);
}