using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using CounterDrone.Core;
using CounterDrone.Core.Models;
using CounterDrone.Core.Repository;
using CounterDrone.Core.Services;
using Xunit;

namespace CounterDrone.Core.Tests
{
    public class DataServiceTests : IDisposable
    {
        private readonly string _testDir;
        private readonly SQLite.SQLiteConnection _db;
        private readonly IDataService _service;

        public DataServiceTests()
        {
            _testDir = Path.Combine(Path.GetTempPath(), $"cd_ds_{Guid.NewGuid():N}");
            var paths = new TestPathProvider(_testDir);
            _db = new DatabaseManager(paths).OpenMainDb();
            _service = new DataService(
                new AmmunitionSpecRepository(_db),
                new FireUnitSpecRepository(_db),
                new DroneSpecRepository(_db),
                new SensorSpecRepository(_db),
                new EnvironmentSpecRepository(_db),
                new FormationTemplateRepository(_db),
                new RouteTemplateRepository(_db));
        }

        public void Dispose()
        {
            _db?.Close();
            if (Directory.Exists(_testDir)) Directory.Delete(_testDir, true);
        }

        // ══════════════════════════════ DroneSpec ══════════════════════════════

        [Fact]
        public void DroneSpec_SaveAndGet()
        {
            var spec = new DroneSpec
            {
                Id = "test-drone", Name = "Test Drone", DroneType = (int)DroneType.FixedWing,
                PowerType = (int)PowerType.Piston, TypicalSpeed = 150, TypicalAltitude = 500,
            };
            _service.SaveDrone(spec);
            var result = _service.GetDrone("test-drone");
            Assert.NotNull(result);
            Assert.Equal("Test Drone", result.Name);
            Assert.Equal(150, result.TypicalSpeed);
        }

        [Fact]
        public void DroneSpec_Save_UpdateExisting()
        {
            _service.SaveDrone(new DroneSpec { Id = "test-drone", Name = "Old", TypicalSpeed = 100 });
            _service.SaveDrone(new DroneSpec { Id = "test-drone", Name = "New", TypicalSpeed = 200 });
            var result = _service.GetDrone("test-drone");
            Assert.Equal("New", result.Name);
            Assert.Equal(200, result.TypicalSpeed);
        }

        [Fact]
        public void DroneSpec_Delete()
        {
            _service.SaveDrone(new DroneSpec { Id = "test-drone", Name = "ToDelete" });
            _service.DeleteDrone("test-drone");
            Assert.Null(_service.GetDrone("test-drone"));
        }

        [Fact]
        public void DroneSpec_GetAll()
        {
            _service.SaveDrone(new DroneSpec { Id = "d1", Name = "D1" });
            _service.SaveDrone(new DroneSpec { Id = "d2", Name = "D2" });
            var all = _service.GetAllDrones();
            Assert.True(all.Count >= 2);
        }

        // ══════════════════════════════ FireUnitSpec ═══════════════════════════

        [Fact]
        public void FireUnitSpec_SaveAndGet()
        {
            var spec = new FireUnitSpec
            {
                Id = "test-fu", Name = "Test Unit", PlatformType = (int)PlatformType.GroundBased,
                GunCount = 4, MuzzleVelocity = 800,
            };
            _service.SaveFireUnit(spec);
            var result = _service.GetFireUnit("test-fu");
            Assert.NotNull(result);
            Assert.Equal("Test Unit", result.Name);
            Assert.Equal(800, result.MuzzleVelocity);
        }

        [Fact]
        public void FireUnitSpec_Delete()
        {
            _service.SaveFireUnit(new FireUnitSpec { Id = "test-fu", Name = "ToDelete" });
            _service.DeleteFireUnit("test-fu");
            Assert.Null(_service.GetFireUnit("test-fu"));
        }

        [Fact]
        public void FireUnitSpec_GetAll()
        {
            _service.SaveFireUnit(new FireUnitSpec { Id = "f1", Name = "F1" });
            _service.SaveFireUnit(new FireUnitSpec { Id = "f2", Name = "F2" });
            var all = _service.GetAllFireUnits();
            Assert.True(all.Count >= 2);
        }

        // ══════════════════════════════ SensorSpec ═════════════════════════════

        [Fact]
        public void SensorSpec_SaveAndGet()
        {
            var spec = new SensorSpec { Id = "test-sensor", Name = "Test Sensor", RadarRange = 5000 };
            _service.SaveSensor(spec);
            var result = _service.GetSensor("test-sensor");
            Assert.Equal(5000, result.RadarRange);
        }

        [Fact]
        public void SensorSpec_Delete()
        {
            _service.SaveSensor(new SensorSpec { Id = "test-sensor", Name = "Del" });
            _service.DeleteSensor("test-sensor");
            Assert.Null(_service.GetSensor("test-sensor"));
        }

        // ══════════════════════════════ EnvironmentSpec ════════════════════════

        [Fact]
        public void EnvironmentSpec_SaveAndGet()
        {
            var spec = new EnvironmentSpec { Id = "test-env", Name = "Fog", WeatherType = 2, Visibility = 500 };
            _service.SaveEnvironment(spec);
            var result = _service.GetEnvironment("test-env");
            Assert.Equal(500, result.Visibility);
        }

        // ══════════════════════════════ FormationTemplate ══════════════════════

        [Fact]
        public void FormationTemplate_SaveAndGet()
        {
            var spec = new FormationTemplate { Id = "test-fmt", Name = "Test Formation", FormationMode = 1, LateralCount = 3 };
            _service.SaveFormation(spec);
            var result = _service.GetFormation("test-fmt");
            Assert.Equal(3, result.LateralCount);
        }

        // ══════════════════════════════ RouteTemplate ══════════════════════════

        [Fact]
        public void RouteTemplate_SaveAndGet()
        {
            var spec = new RouteTemplate { Id = "test-route", Name = "Test Route" };
            _service.SaveRoute(spec);
            var result = _service.GetRoute("test-route");
            Assert.Equal("Test Route", result.Name);
        }
    }
}
