using System;
using FairyGUI;
using FairyGUI.Utils;
using System.Collections;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using Object = UnityEngine.Object;

namespace NBF
{
    [Serializable]
    public class ModelViewRenderImage
    {
        public Transform modelRoot { get; private set; }
        public Camera Camera => _camera;
        public RenderTexture RT => _renderTexture;

        public ModelViewerSettings ViewerSettings { get; private set; }
        Camera _camera;
        Image _image;
        Transform _root;
        Transform _background;
        Transform _model;
        RenderTexture _renderTexture;
        int _width;
        int _height;
        bool _cacheTexture;
        // Vector3 _rotating;

        const int RENDER_LAYER = 22;
        const int HIDDEN_LAYER = 22;


        public ModelViewRenderImage(GGraph holder)
        {
            _width = (int)holder.width;
            _height = (int)holder.height;
            _cacheTexture = true;

            _image = new Image();
            holder.SetNativeObject(_image);


            _root = new GameObject("RenderImage").transform;
            _root.transform.position = Vector3.zero;
            // _root.SetParent(_camera.transform, false);
            SetLayer(_root.gameObject, HIDDEN_LAYER);
            Object.DontDestroyOnLoad(_root.gameObject);

            Object prefab = Resources.Load("RenderTexture/RenderImageCamera");
            GameObject go = (GameObject)Object.Instantiate(prefab, _root, false);

            _camera = go.GetComponent<Camera>();
            _camera.transform.position = Vector3.zero;
            _camera.cullingMask = 1 << RENDER_LAYER;
            _camera.enabled = false;
            Object.DontDestroyOnLoad(_camera.gameObject);


            modelRoot = new GameObject("model_root").transform;
            modelRoot.SetParent(_root, false);

            _background = new GameObject("background").transform;
            _background.SetParent(_root, false);

            _image.onAddedToStage.Add(OnAddedToStage);
            _image.onRemovedFromStage.Add(OnRemoveFromStage);


            // _viewerSettings = new ModelViewerSettings();

            if (_image.stage != null)
                OnAddedToStage();
            else
                _camera.gameObject.SetActive(false);
        }

        public void SetModel(GameObject model, ModelViewerSettings settings)
        {
            this.UnloadModel();
            ViewerSettings = settings;
            if (model == null) return;
            var joint = model.GetComponent<Joint>();
            if (joint != null)
            {
                Object.Destroy(joint);
            }

            _model = model.transform;
            _model.SetParent(this.modelRoot, false);
            _model.localPosition = Vector3.zero;
            _model.localScale = Vector3.one;
            _model.localEulerAngles = Vector3.zero;
            if (ViewerSettings == null)
            {
                ViewerSettings = new ModelViewerSettings();
                ModelViewerUtils.InitSetting(model, ViewerSettings);
            }

            var meshArr = _model.GetComponentsInChildren<MeshRenderer>();
            foreach (var meshRenderer in meshArr)
            {
                // 设置物体仅接受 Layer 2 的光照
                meshRenderer.renderingLayerMask = 1 << 2;
            }


            Review();
        }

        public void UnloadModel()
        {
            if (_model != null)
            {
                ViewerSettings = null;
                _model.gameObject.SetActive(false);
                Object.Destroy(_model.gameObject);
                _model = null;
            }
        }


        public void Review()
        {
            _model.position = ViewerSettings.objectPosition;
            _model.localScale = ViewerSettings.objectScale;
            _model.eulerAngles = ViewerSettings.objectRotation;


            _camera.clearFlags = CameraClearFlags.Nothing;
            _camera.backgroundColor = new Color(0, 0, 0, 0); // 完全透明
            _camera.transform.position = ViewerSettings.cameraPosition;
            _camera.transform.LookAt(ViewerSettings.cameraTarget);
            _camera.orthographic = ViewerSettings.cameraOrtho;
            _camera.orthographicSize = ViewerSettings.cameraSize;
            _camera.orthographicSize /= ViewerSettings.camerasScaleFactor;

            _camera.fieldOfView = ViewerSettings.cameraFov;
            float fov = 2 * Mathf.Rad2Deg * Mathf.Atan2(
                Mathf.Tan(_camera.fieldOfView * Mathf.Deg2Rad / 2), ViewerSettings.camerasScaleFactor
            );
            if (fov < 0)
                fov += 180;
            _camera.fieldOfView = fov;

            _camera.nearClipPlane = 0.001f;
            _camera.farClipPlane = 10000;
            _camera.depthTextureMode = DepthTextureMode.Depth;
            _camera.clearFlags = CameraClearFlags.Color;
            _camera.GetUniversalAdditionalCameraData().renderPostProcessing = false; //URP only
        }

        public void Dispose()
        {
            UnloadModel();
            Object.Destroy(_camera.gameObject);
            DestroyTexture();

            _image.Dispose();
            _image = null;
        }


        void CreateTexture()
        {
            if (_renderTexture != null)
                return;

            //1920

            _renderTexture = new RenderTexture(_width, _height, 24, RenderTextureFormat.ARGB32)
            {
                antiAliasing = 8,
                filterMode = FilterMode.Bilinear,
                anisoLevel = 0,
                useMipMap = false
            };
            // _renderTexture.Create();
            _image.texture = new NTexture(_renderTexture);
            _image.shader = "Unlit/Transparent";
        }

        void DestroyTexture()
        {
            if (_renderTexture != null)
            {
                Object.Destroy(_renderTexture);
                _renderTexture = null;
                _image.texture = null;
            }
        }

        void OnAddedToStage()
        {
            if (_renderTexture == null)
                CreateTexture();

            Timers.inst.AddUpdate(Render);
            _camera.gameObject.SetActive(true);

            Render();
        }

        void OnRemoveFromStage()
        {
            if (!_cacheTexture)
                DestroyTexture();

            Timers.inst.Remove(Render);
            _camera.gameObject.SetActive(false);
        }

        void Render(object param = null)
        {
            // if (_rotating != Vector3.zero && this.modelRoot != null)
            // {
            //     // 使用 Quaternion 来避免欧拉角带来的问题
            //     modelRoot.Rotate(_rotating, Space.World);
            // }

            SetLayer(_root.gameObject, RENDER_LAYER);

            _camera.targetTexture = _renderTexture;
            RenderTexture old = RenderTexture.active;
            RenderTexture.active = _renderTexture;
            GL.Clear(true, true, Color.clear);
            _camera.Render();
            RenderTexture.active = old;

            SetLayer(_root.gameObject, HIDDEN_LAYER);

            UpdateDebugSave();
        }

        void SetLayer(GameObject go, int layer)
        {
            Transform[] transforms = go.GetComponentsInChildren<Transform>(true);
            foreach (Transform t in transforms)
            {
                t.gameObject.layer = layer;
            }
        }

        #region 旋转

        // 在 ModelViewRenderImage 中添加新字段
        private Vector2 _lastMousePosition;

        private bool _isDragging;

        public void StartRotate(Vector2 currentMousePosition)
        {
            _lastMousePosition = currentMousePosition;
            _isDragging = true;
        }

        public void UpdateRotation(Vector2 currentMousePosition)
        {
            if (!_isDragging || modelRoot == null || _camera == null) return;

            Vector2 delta = currentMousePosition - _lastMousePosition;

            // 使用适中的灵敏度
            float sensitivity = 0.2f;
            float rotX = -delta.y * sensitivity;
            float rotY = -delta.x * sensitivity;

            Quaternion yRotation = Quaternion.AngleAxis(rotY, _camera.transform.up);
            Quaternion xRotation = Quaternion.AngleAxis(rotX, _camera.transform.right);

            // 组合旋转并应用
            modelRoot.rotation = yRotation * xRotation * modelRoot.rotation;

            _lastMousePosition = currentMousePosition;
        }

        public void StopRotate()
        {
            _isDragging = false;
        }

        // 重置到初始状态的方法
        public void ResetToInitialRotation()
        {
            modelRoot.localRotation = Quaternion.identity;
            _isDragging = false;
        }

        #endregion


        #region MyRegion

        void UpdateDebugSave()
        {
            if (Input.GetKeyDown(KeyCode.F9))
            {
                SaveRenderTextureToPNG(_renderTexture, "RenderTextureDebug.png");
            }
        }

        void SaveRenderTextureToPNG(RenderTexture rt, string fileName)
        {
            if (rt == null)
            {
                Debug.LogWarning("RenderTexture 为 null，无法保存。");
                return;
            }

            RenderTexture current = RenderTexture.active;
            RenderTexture.active = rt;

            Texture2D tex = new Texture2D(rt.width, rt.height, TextureFormat.RGBA32, false);
            tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
            tex.Apply();

            byte[] bytes = tex.EncodeToPNG();
            string path = System.IO.Path.Combine(Application.dataPath, "../" + fileName);
            System.IO.File.WriteAllBytes(path, bytes);
            Debug.Log($"✅ RenderTexture 已保存到: {path}");

            UnityEngine.Object.Destroy(tex);
            RenderTexture.active = current;
        }

        #endregion
    }
}