using System;
using System.Collections.Generic;
using System.IO;
using CounterDrone.Core;
using CounterDrone.Core.Models;
using SQLite;

namespace CounterDrone.Core.Tests
{
    /// <summary>测试辅助：从 seeded 数据库读取（与生产环境同源）</summary>
    internal static class TestData
    {
        private static readonly string _tempDir;
        private static readonly SQLiteConnection _db;

        static TestData()
        {
            _tempDir = Path.Combine(Path.GetTempPath(), $"cd_td_{Guid.NewGuid():N}");
            var paths = new TestPathProvider(_tempDir);
            var dbm = new DatabaseManager(paths);
            _db = dbm.OpenMainDb();
        }

        private static List<AmmunitionSpec>? _ammo;
        public static List<AmmunitionSpec> Ammo =>
            _ammo ??= new List<AmmunitionSpec>(_db.Table<AmmunitionSpec>());

        private static DroneSpec? _droneSpec;
        public static DroneSpec DefaultDroneSpec => _droneSpec ??= _db.Table<DroneSpec>().First(d => d.Id == "shahed");

        private static LaunchPlatformSpec? _groundSpec;
        public static LaunchPlatformSpec GroundSpec => _groundSpec ??= _db.Table<LaunchPlatformSpec>().First(f => f.Id == "ground-light");

        public static ScenarioDrone CreateScenarioDrone(string waveId = "w1", int quantity = 1)
            => new() { DroneSpecId = DefaultDroneSpec.Id, WaveId = waveId, Quantity = quantity };

        public static ScenarioDrone CreateScenarioDroneWithId(string scenarioId, string waveId = "w1", int quantity = 1)
            => new() { ScenarioId = scenarioId, DroneSpecId = DefaultDroneSpec.Id, WaveId = waveId, Quantity = quantity };

        public static ScenarioUnit CreateScenarioUnit(double px, double py, double pz,
            int ammoType = 0, int? munitionCount = null)
            => new() { LaunchPlatformSpecId = "ground-light", SensorSpecId = "radar-sr", PositionX = px, PositionY = py, PositionZ = pz,
                       AerosolType = ammoType, MunitionCount = munitionCount ?? 8, Quantity = 1 };

        private static LaunchPlatformSpec? _defaultFuSpec;
        public static LaunchPlatformSpec DefaultFuSpec => _defaultFuSpec ??= new LaunchPlatformSpec
        {
            Id = "test-fu", PlatformType = (int)PlatformType.GroundBased,
            GunCount = 1, ChannelsPerGun = 8, ChannelInterval = 1,
            MuzzleVelocity = 800, Cooldown = 5, AmmoChangeTime = 30,
        };

        private static SensorSpec? _sensorSpec;
        public static SensorSpec DefaultSensorSpec => _sensorSpec ??= new SensorSpec
        {
            Id = "test-sensor", RadarRange = 3000, Accuracy = 50,
        };

        public static ScenarioUnit CreateDetectionUnit(double px, double py, double pz)
            => new()
            {
                SensorSpecId = "radar-mr",
                EquipmentRole = (int)EquipmentRole.Detection,
                PositionX = px, PositionY = py, PositionZ = pz, Quantity = 1
            };

        public static Dictionary<string, DroneSpec> EmptyDroneSpecs => new();
        public static Dictionary<string, LaunchPlatformSpec> EmptyFuSpecs => new();
        public static Dictionary<string, SensorSpec> EmptySensorSpecs => new();

        private static DefaultData? _all;
        public static DefaultData All
        {
            get
            {
                if (_all == null)
                {
                    var dir = TestPathProvider.FindProjectDataDirectory()!;
                    _all = DefaultData.Load(new DirPathProvider(dir));
                }
                return _all;
            }
        }

        private class DirPathProvider : IPathProvider
        {
            private readonly string _dir;
            public DirPathProvider(string dir) => _dir = dir;
            public string GetDataRoot() => _dir;
            public string GetMainDbPath() => throw new NotImplementedException();
            public string GetFramesDir() => throw new NotImplementedException();
            public string GetModelsDir() => throw new NotImplementedException();
            public string GetFontPath() => throw new NotImplementedException();
        }

        public static void Cleanup()
        {
            _db?.Close();
            if (Directory.Exists(_tempDir)) Directory.Delete(_tempDir, true);
        }
    }
}
