using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
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
    {
        private bool _loggedStart;

        [SerializeField] private GameObject _dronePrefab;
        [SerializeField] private GameObject _cloudPrefab;
        [SerializeField] private GameObject _platformPrefab;

        private SimulationEngine _engine;
        private FrameDataStore _frameStore;
        private IScenarioService _scenario;
        private IPathProvider _paths;
        private string _taskId;
        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;

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

            _scenario = new ScenarioService(
                new SimTaskRepository(_db), new CombatSceneRepository(_db),
                new ControlZoneRepository(_db), new TargetConfigRepository(_db),
                new EquipmentDeploymentRepository(_db), new CloudDispersalRepository(_db),
                new RoutePlanRepository(_db), new WaypointRepository(_db));

            _frameStore = new FrameDataStore(_paths);
            _engine = new SimulationEngine(_scenario, _frameStore, new DamageModelRouter(), _paths, new DefaultDefensePlanner(DefaultAmmunition.GetAll()));
        }

        public void LoadAndStart(string taskId)
        {
            _taskId = taskId;
            var detail = _scenario.GetTaskDetail(taskId);
            if (detail == null) { Debug.LogError("Task not found"); return; }

            _engine.Initialize(taskId);

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

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

            if (!_loggedStart) { Debug.Log($"Ticking: drones={_engine.Drones.Count}, timescale={_engine.TimeScale}"); _loggedStart = true; }

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

            // 每秒输出无人机位置
            if (Time.frameCount % 60 == 0 && _engine.Drones.Count > 0)
            {
                var d = _engine.Drones[0];
                Debug.Log($"Drone: ({d.PosX:F0}, {d.PosY:F0}, {d.PosZ:F0}) Status={d.Status}");
            }

            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)
                {
                    float r = ParseCloudRadius(snap.StateData);
                    float opacity = ParseCloudOpacity(snap.StateData);
                    go.transform.localScale = UVector3.one * r;
                    var mat = go.GetComponent<Renderer>().material;
                    mat.color = new Color(1, 0, 0, opacity);
                }
            }

            foreach (var cloud in _engine.Clouds)
            {
                if (!_clouds.ContainsKey(cloud.Id))
                {
                    var pos = new UVector3(cloud.Dispersion.Center.X, cloud.Dispersion.Center.Y, cloud.Dispersion.Center.Z);
                    var prefab = _cloudPrefab != null ? _cloudPrefab : GameObject.CreatePrimitive(PrimitiveType.Sphere);
                    var go = Instantiate(prefab, pos, Quaternion.identity);
                    go.name = cloud.Id;
                    float r = cloud.Dispersion.Radius;
                    go.transform.localScale = UVector3.one * r;
                    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);
                }
            }

            if (result.State == SimulationState.Completed)
                Debug.Log($"Simulation done. Drone: {_engine.Drones[0].Status}, HP: {_engine.Drones[0].Hp:F2}");
        }

        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;
        }

        private float ParseCloudOpacity(string stateData)
        {
            try
            {
                using var doc = JsonDocument.Parse(stateData);
                if (doc.RootElement.TryGetProperty("opacity", out var o))
                    return o.GetSingle();
            }
            catch { }
            return 0.5f;
        }

        private float ParseCloudRadius(string stateData)
        {
            try
            {
                using var doc = JsonDocument.Parse(stateData);
                if (doc.RootElement.TryGetProperty("radius", out var r))
                    return r.GetSingle();
            }
            catch { }
            return 1f;
        }
    }
}
