using System.Collections.Generic;
using System.Linq;
using CounterDrone.Core;
using CounterDrone.Core.Algorithms;
using CounterDrone.Core.Models;
using CounterDrone.Core.Repository;
using CounterDrone.Core.Services;
using CounterDrone.Core.Simulation;
using UnityEngine;
using UVector3 = UnityEngine.Vector3;
using AVector3 = CounterDrone.Core.Algorithms.Vector3;

namespace CounterDrone.Unity
{
    public class SimulationRunner : MonoBehaviour
    {
        [SerializeField] private GameObject _dronePrefab;
        [SerializeField] private GameObject _cloudPrefab;
        [SerializeField] private GameObject _platformPrefab;

        private SimulationEngine _engine;
        private FrameDataStore _frameStore;
        public FrameDataStore FrameStore => _frameStore;
        private IScenarioService _scenario;
        private IPathProvider _paths;
        private string _scenarioId;
        private SQLite.SQLiteConnection _db;

        private readonly Dictionary<string, GameObject> _entityVisuals = new();
        private readonly Dictionary<string, GameObject> _clouds = new();
        private readonly HashSet<string> _knownMunitions = new();
        private readonly HashSet<string> _knownPlatforms = new();

        public SimulationEngine Engine => _engine;

        private IDataService _dataService;
        public IDataService DataService { get => _dataService; set => _dataService = value; }

        public void Awake()
        {
            _paths = new UnityPathProvider();
            _db = new DatabaseManager(_paths).OpenMainDb();
            SqliteConnectionTracker.Track(_db);

            _scenario = new ScenarioService(
                new ScenarioRepository(_db), new CombatSceneRepository(_db),
                new ControlZoneRepository(_db), new ScenarioDroneRepository(_db),
                new ScenarioUnitRepository(_db), new CloudDispersalRepository(_db),
                new RoutePlanRepository(_db), new WaypointRepository(_db));

            _frameStore = new FrameDataStore(_paths);
            _engine = new SimulationEngine(_scenario, _frameStore, new DamageModelRouter(), _paths, new DefensePlanner(DefaultData.Load(_paths).Ammunition, PlannerConfig.Load(_paths)));
        }

        public void LoadAndStart(string scenarioId)
        {
            _scenarioId = scenarioId;
            var detail = _scenario.GetScenarioDetail(scenarioId);
            if (detail == null) { Debug.LogError("scenario not found"); return; }

            _engine.Initialize(scenarioId);

            foreach (var drone in _engine.Drones)
                SpawnDroneVisual(drone);
        }

        void Update()
        {
            if (_engine == null || _engine.State != SimulationState.Running) return;

            var result = _engine.Tick(Time.deltaTime);

            foreach (var snap in result.EntitySnapshots)
            {
                if (!_entityVisuals.TryGetValue(snap.EntityId, out var go) || go == null)
                {
                    // 新出现的实体（如空基平台在首次帧快照中）
                    if (snap.EntityType == EntityType.Platform)
                    {
                        SpawnPlatformVisual(snap);
                        if (!_entityVisuals.TryGetValue(snap.EntityId, out go) || go == null) continue;
                    }
                    else continue;
                }
                go.transform.position = new UVector3(snap.PosX, snap.PosY, snap.PosZ);

                if (snap.EntityType == EntityType.Cloud)
                {
                    go.transform.localScale = UVector3.one * snap.CloudRadius;
                    var mat = go.GetComponent<Renderer>().material;
                    mat.color = new Color(1, 0, 0, snap.CloudOpacity);
                }
            }

            foreach (var cloud in _engine.Clouds)
            {
                if (!_clouds.ContainsKey(cloud.Id))
                {
                    var pos = new UVector3(cloud.PosX, cloud.PosY, cloud.PosZ);
                    var prefab = _cloudPrefab != null ? _cloudPrefab : GameObject.CreatePrimitive(PrimitiveType.Sphere);
                    var go = Instantiate(prefab, pos, Quaternion.identity);
                    go.name = cloud.Id;
                    go.transform.localScale = UVector3.one * cloud.Radius;
                    var mat = go.GetComponent<Renderer>().material;
                    mat.color = new Color(1, 0, 0, 0.3f);
                    _clouds[cloud.Id] = go;
                    _entityVisuals[cloud.Id] = go;
                }
            }

            // 炮弹飞行轨迹
            foreach (var m in _engine.Munitions)
            {
                if (!_knownMunitions.Contains(m.Id))
                {
                    var go = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                    go.name = m.Id;
                    go.transform.localScale = new UVector3(2, 10, 2);
                    _knownMunitions.Add(m.Id);
                    _entityVisuals[m.Id] = go;
                }
                if (_entityVisuals.TryGetValue(m.Id, out var mgo))
                    mgo.transform.position = new UVector3(m.PosX, m.PosY, m.PosZ);
            }

            // 清理已到达的炮弹（已转为云团）
            foreach (var id in _knownMunitions.ToArray())
            {
                if (!_engine.Munitions.Any(m => m.Id == id) && _entityVisuals.TryGetValue(id, out var go))
                {
                    Destroy(go);
                    _knownMunitions.Remove(id);
                    _entityVisuals.Remove(id);
                }
            }

        }

        public void Stop() => _engine?.Stop();
        void OnDisable() { SqliteConnectionTracker.Untrack(_db); _db?.Dispose(); _db = null; }
        void OnDestroy() => Stop();

        private void SpawnDroneVisual(DroneEntity drone)
        {
            var prefab = _dronePrefab != null ? _dronePrefab : GameObject.CreatePrimitive(PrimitiveType.Cube);
            var go = Instantiate(prefab, new UVector3(drone.PosX, drone.PosY, drone.PosZ), Quaternion.identity);
            go.name = drone.Id;
            go.transform.localScale = UVector3.one * 50f;
            _entityVisuals[drone.Id] = go;
        }

        private void SpawnPlatformVisual(EntitySnapshot snap)
        {
            if (_knownPlatforms.Contains(snap.EntityId)) return;
            _knownPlatforms.Add(snap.EntityId);
            var prefab = _platformPrefab != null ? _platformPrefab : GameObject.CreatePrimitive(PrimitiveType.Capsule);
            var go = Instantiate(prefab, new UVector3(snap.PosX, snap.PosY, snap.PosZ), Quaternion.identity);
            go.name = snap.EntityId;
            go.transform.localScale = new UVector3(30, 80, 30);
            var mat = go.GetComponent<Renderer>().material;
            mat.color = new Color(0.2f, 0.5f, 1f, 0.8f); // 蓝色半透明 = 空基平台
            _entityVisuals[snap.EntityId] = go;
        }
    }
}
