using System.Collections.Generic;
using UnityEngine;

namespace IndianOceanAssets.Engine2_5D
{
    /// <summary>
    /// 黑暗遮罩管理器 v2 —— 乘法混合 + 编辑器开关（不含回声）。
    /// 回声描边已独立到 EchoSystem + SpriteEchoOutline shader。
    ///
    /// 单例模式：收集场景中所有 LightSource，每帧把位置/半径/强度
    /// 写入 DarknessOverlay 材质的 _LightData 数组。
    ///
    /// 使用方式：
    /// 1. 在场景中创建一个空物体，挂上此脚本
    /// 2. 创建一个大平面（覆盖可视区域），Y 稍高于精灵
    /// 3. 给平面分配使用 DarknessOverlay shader 的材质
    /// 4. 把该材质拖到此脚本的 darknessMaterial 字段
    /// </summary>
    public class LightMaskSystem : MonoBehaviour
    {
        public static LightMaskSystem Instance { get; private set; }

        [Header("遮罩材质（使用 DarknessOverlay shader）")]
        [SerializeField] private Material darknessMaterial;

        [Header("编辑器开关")]
        [Tooltip("勾选后关闭黑暗，所有物件完全可见，方便摆放场景。\n取消勾选恢复黑暗效果。")]
        [SerializeField] private bool debugShowAll = false;

        [Header("黑暗设置")]
        [Tooltip("最小亮度：0=纯黑（精灵完全看不见），0.05=微微看到轮廓")]
        [SerializeField, Range(0f, 0.3f)] private float minBrightness = 0f;

        [Tooltip("黑暗底色：夜间微光色调，接近纯黑")]
        [SerializeField] private Color darknessColor = new Color(0.01f, 0.01f, 0.02f, 1f);

        [Tooltip("光线边缘柔和度，0 = 硬边，1 = 最柔")]
        [SerializeField, Range(0.01f, 1f)] private float lightSoftness = 0.35f;

        [Header("遮罩平面跟随设置")]
        [Tooltip("如果勾选，遮罩平面会跟随摄像机移动（适合大地图）")]
        [SerializeField] private bool followCamera = true;
        [SerializeField] private Transform maskPlane;
        [SerializeField] private Vector3 maskOffset = new Vector3(0f, 5f, 0f);
        [SerializeField] private float planeSize = 50f;

        // Shader Property IDs
        private static readonly int LightDataID     = Shader.PropertyToID("_LightData");
        private static readonly int LightCountID    = Shader.PropertyToID("_LightCount");
        private static readonly int DarknessColorID = Shader.PropertyToID("_DarknessColor");
        private static readonly int MinBrightnessID = Shader.PropertyToID("_MinBrightness");
        private static readonly int LightSoftnessID = Shader.PropertyToID("_LightSoftness");

        private readonly List<LightSource> _lights = new List<LightSource>();
        private Vector4[] _lightData = new Vector4[64];
        private Camera _mainCamera;

        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(this);
                return;
            }
            Instance = this;
        }

        private void Start()
        {
            _mainCamera = Camera.main;
            UpdateMaterialProperties();
        }

        private void Update()
        {
            UpdateLightData();
            UpdateMaskPosition();
        }

        private void UpdateMaterialProperties()
        {
            if (darknessMaterial == null) return;
            darknessMaterial.SetColor(DarknessColorID, darknessColor);
            darknessMaterial.SetFloat(LightSoftnessID, lightSoftness);

            if (debugShowAll)
                darknessMaterial.SetFloat(MinBrightnessID, 1.0f);
            else
                darknessMaterial.SetFloat(MinBrightnessID, minBrightness);
        }

        private void UpdateLightData()
        {
            if (darknessMaterial == null) return;

            int writeIndex = 0;
            for (int i = 0; i < _lights.Count && writeIndex < 64; i++)
            {
                var src = _lights[i];
                if (src == null || !src.gameObject.activeInHierarchy)
                    continue;

                Vector2 pos = src.GetWorldPositionXZ();
                _lightData[writeIndex] = new Vector4(pos.x, pos.y, src.Radius, src.Intensity);
                writeIndex++;
            }

            darknessMaterial.SetVectorArray(LightDataID, _lightData);
            darknessMaterial.SetInt(LightCountID, writeIndex);
        }

        private void UpdateMaskPosition()
        {
            if (!followCamera || maskPlane == null || _mainCamera == null) return;
            Vector3 camPos = _mainCamera.transform.position;
            maskPlane.position = new Vector3(camPos.x + maskOffset.x, maskOffset.y, camPos.z + maskOffset.z);
        }

        // ===== 光源注册/注销 =====

        public void RegisterLight(LightSource source)
        {
            if (!_lights.Contains(source))
                _lights.Add(source);
        }

        public void UnregisterLight(LightSource source)
        {
            _lights.Remove(source);
        }

        // ===== Inspector 同步 =====

        private void OnValidate()
        {
            if (darknessMaterial == null) return;
            darknessMaterial.SetColor(DarknessColorID, darknessColor);
            darknessMaterial.SetFloat(LightSoftnessID, lightSoftness);

            if (debugShowAll)
                darknessMaterial.SetFloat(MinBrightnessID, 1.0f);
            else
                darknessMaterial.SetFloat(MinBrightnessID, minBrightness);
        }

        /// <summary>
        /// 快捷切换黑暗开关（右键组件 > Toggle Darkness）
        /// </summary>
        [ContextMenu("Toggle Darkness (Debug)")]
        private void ToggleDarknessDebug()
        {
            debugShowAll = !debugShowAll;
            OnValidate();
            Debug.Log($"[LightMaskSystem] Darkness {(debugShowAll ? "OFF (debug)" : "ON")}");
        }

        // ===== 运行时动态调整 =====

        /// <summary>
        /// 动态调整最小亮度（白天/黑夜切换、Q键过场点亮等）
        /// 0 = 纯黑（完全看不见），0.3 = 能模糊看到东西
        /// </summary>
        public void SetMinBrightness(float value)
        {
            minBrightness = Mathf.Clamp01(value);
            if (darknessMaterial != null && !debugShowAll)
                darknessMaterial.SetFloat(MinBrightnessID, minBrightness);
        }

        /// <summary>
        /// 动态调整黑暗底色
        /// </summary>
        public void SetDarknessColor(Color color)
        {
            darknessColor = color;
            if (darknessMaterial != null)
                darknessMaterial.SetColor(DarknessColorID, darknessColor);
        }
    }
}