using System;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Npgsql;
using PhoenixLib.Logging;
using WingsEmu.Plugins.GameEvents.Configuration.InstantBattle;

namespace WingsEmu.Plugins.GameEvents.Services
{
    public class GameEventConfigPostgresSyncService : IHostedService
    {
        private readonly IGlobalInstantBattleConfiguration _configuration;

        public GameEventConfigPostgresSyncService(IGlobalInstantBattleConfiguration configuration)
        {
            _configuration = configuration;
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            try
            {
                string host = Environment.GetEnvironmentVariable("DATABASE_IP")
                              ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_IP")
                              ?? "127.0.0.1";
                string port = Environment.GetEnvironmentVariable("DATABASE_PORT")
                              ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_PORT")
                              ?? "5432";
                string db = Environment.GetEnvironmentVariable("DATABASE_NAME")
                            ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_NAME")
                            ?? "game";
                string user = Environment.GetEnvironmentVariable("DATABASE_USER")
                              ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_USER")
                              ?? "postgres";
                string pass = Environment.GetEnvironmentVariable("DATABASE_PASSWORD")
                              ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_PASSWORD")
                              ?? "postgres";

                using var conn = new NpgsqlConnection($"Host={host};Port={port};Database={db};Username={user};Password={pass}");
                conn.Open();
                using var tx = conn.BeginTransaction();

                using (var cmd = new NpgsqlCommand(@"CREATE TABLE IF NOT EXISTS gameevent_instant_battle_configs (
  id BIGSERIAL PRIMARY KEY,
  map_id INT,
  game_event_type INT,
  config_json JSONB
);", conn, tx)) cmd.ExecuteNonQuery();

                using (var cmd = new NpgsqlCommand("TRUNCATE TABLE gameevent_instant_battle_configs RESTART IDENTITY;", conn, tx)) cmd.ExecuteNonQuery();

                var configs = (_configuration as GlobalInstantBattleConfiguration)?.Configurations ?? Enumerable.Empty<InstantBattleConfiguration>();

                foreach (InstantBattleConfiguration c in configs)
                {
                    using var cmd = new NpgsqlCommand("INSERT INTO gameevent_instant_battle_configs(map_id,game_event_type,config_json) VALUES (@map,@type,@cfg::jsonb);", conn, tx);
                    cmd.Parameters.AddWithValue("map", c.MapId);
                    cmd.Parameters.AddWithValue("type", (int)c.GameEventType);
                    cmd.Parameters.AddWithValue("cfg", JsonSerializer.Serialize(c));
                    cmd.ExecuteNonQuery();
                }

                tx.Commit();
                Log.Info($"[PARSER_DB_SYNC] Synced instant_battle_configs={configs.Count()}");
            }
            catch (Exception ex)
            {
                Log.Error("[PARSER_DB_SYNC] Failed to sync gameevents", ex);
            }

            return Task.CompletedTask;
        }

        public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
    }
}
