using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using DG.Tweening;
using TMPro;

namespace com.al_arcade.tf
{
    using shared;

    [AddComponentMenu("Science Street/TF Demo Builder")]
    public class TfDemoBuilder : MonoBehaviour
    {
        [Header("Build Configuration")]
        [SerializeField] private string buildType = "scistreet";
        [SerializeField] private int gradeId = 0;
        [SerializeField] private int questionCount = 15;
        [SerializeField] private string classCode = "";

        [Header("Game Settings")]
        [SerializeField] private int stepsToWin = 5;
        [SerializeField] private float stepDistance = 3f;

        [Header("Arabic Font")]
        [Tooltip("Drag your Arabic TMP_FontAsset here")]
        [SerializeField] private TMP_FontAsset arabicFont;

        [Header("Debug")]
        [SerializeField] private bool useOfflineTestData = false;

        private TfGameManager _gm;
        private TfHandController _handController;
        private TfProductionLine _productionLine;
        private TfQuestionScreen _questionScreen;
        private TfUIManager _uiManager;

        private Vector3 _camPos;
        private Vector3 _camLookAt;
        private float _lineCenterZ;

        private void Start()
        {
            DOTween.Init();
            if (arabicFont != null) SSFontManager.Font = arabicFont;
            StartCoroutine(BuildEverything());
        }

        private IEnumerator BuildEverything()
        {
            Debug.Log("═══════════════════════════════════════════");
            Debug.Log("  Science Street — T/F Factory (SIDE VIEW)");
            Debug.Log("═══════════════════════════════════════════");

            if (FindObjectOfType<EventSystem>() == null)
            {
                var es = new GameObject("EventSystem");
                es.AddComponent<EventSystem>();
                es.AddComponent<StandaloneInputModule>();
            }

            SSApiManager.EnsureInstance();
            SSAudioManager.EnsureInstance();
            SSParticleManager.EnsureInstance();

            var session = SSGameSession.EnsureInstance();
            session.buildType = buildType;
            session.gradeId = gradeId;
            session.questionCount = questionCount;
            session.classCode = classCode;
            yield return null;


            float totalLength = stepsToWin * stepDistance + 10f;
            _lineCenterZ = 2f + totalLength / 2f;
            _camPos = new Vector3(-11f, 3.5f, _lineCenterZ);
            _camLookAt = new Vector3(0f, 1.5f, _lineCenterZ);


            BuildScene(totalLength, _lineCenterZ);
            yield return null;

            SetupCamera();
            yield return null;


            var lineObj = new GameObject("ProductionLine");
            lineObj.transform.position = new Vector3(0, 0, 2);
            _productionLine = lineObj.AddComponent<TfProductionLine>();
            _productionLine.Build(stepsToWin, stepDistance, _camPos);
            yield return null;


            var screenObj = new GameObject("QuestionScreen");
            _questionScreen = screenObj.AddComponent<TfQuestionScreen>();
            Vector3 screenPos = new Vector3(0, 5f, _lineCenterZ);
            _questionScreen.Build(screenPos, _camPos);
            yield return null;


            var handsObj = new GameObject("Hands");
            _handController = handsObj.AddComponent<TfHandController>();
            _handController.Build(Camera.main);
            yield return null;


            var uiObj = new GameObject("TfUI");
            _uiManager = uiObj.AddComponent<TfUIManager>();
            _uiManager.BuildUI();
            if (_uiManager.onRestartClicked == null)
                _uiManager.onRestartClicked = new UnityEvent();
            yield return null;


            var gmObj = new GameObject("TfGameManager");
            _gm = gmObj.AddComponent<TfGameManager>();
            _gm.handController = _handController;
            _gm.productionLine = _productionLine;
            _gm.questionScreen = _questionScreen;
            _gm.uiManager = _uiManager;
            _uiManager.onRestartClicked.AddListener(OnRestartClicked);
            yield return null;

            SetupLighting();
            yield return null;

            Debug.Log("═══════════════════════════════════════════");
            Debug.Log("  T/F Game Ready! A/← = True  D/→ = False");
            Debug.Log("═══════════════════════════════════════════");

            yield return new WaitForSeconds(0.5f);

            if (useOfflineTestData)
                _gm.StartWithQuestions(GetTestQuestions());
            else
                _gm.StartGame();
        }

        private void OnRestartClicked()
        {
            if (_gm != null) _gm.ResetGame();
            SetupCamera();
            if (_gm != null) _gm.StartGame();
        }

        private void SetupCamera()
        {
            var cam = Camera.main;
            if (cam == null) return;
            cam.transform.position = _camPos;
            cam.transform.LookAt(_camLookAt);
            cam.fieldOfView = 55;
            cam.nearClipPlane = 0.1f;
        }


        private void BuildScene(float totalLength, float lineCenterZ)
        {

            Camera.main.clearFlags = CameraClearFlags.SolidColor;
            Camera.main.backgroundColor = new Color32(70, 80, 110, 255);

            var shader = GetShader();
            float sceneDepth = totalLength + 12f;
            float halfDepth = sceneDepth / 2f;


            var floor = GameObject.CreatePrimitive(PrimitiveType.Cube);
            floor.name = "Floor";
            floor.transform.position = new Vector3(0, -0.05f, lineCenterZ);
            floor.transform.localScale = new Vector3(30, 0.1f, sceneDepth);
            floor.GetComponent<Renderer>().material =
                new Material(shader) { color = new Color32(65, 65, 80, 255) };


            for (float x = -12; x <= 12; x += 6f)
            {
                for (float z = lineCenterZ - halfDepth; z < lineCenterZ + halfDepth; z += 6f)
                {
                    var tile = GameObject.CreatePrimitive(PrimitiveType.Cube);
                    tile.name = "Tile";
                    tile.transform.position = new Vector3(x, 0.001f, z);
                    tile.transform.localScale = new Vector3(5.8f, 0.001f, 5.8f);
                    Destroy(tile.GetComponent<Collider>());
                    bool checker = ((int)(x / 6) + (int)(z / 6)) % 2 == 0;
                    tile.GetComponent<Renderer>().material = new Material(shader)
                    {
                        color = checker
                            ? new Color32(60, 60, 75, 255)
                            : new Color32(70, 70, 85, 255)
                    };
                }
            }


            for (int side = -1; side <= 1; side += 2)
            {
                var wall = GameObject.CreatePrimitive(PrimitiveType.Cube);
                wall.name = $"Wall_{(side < 0 ? "L" : "R")}";
                wall.transform.position = new Vector3(side * 15f, 5f, lineCenterZ);
                wall.transform.localScale = new Vector3(0.5f, 10f, sceneDepth);
                Destroy(wall.GetComponent<Collider>());
                wall.GetComponent<Renderer>().material =
                    new Material(shader) { color = new Color32(75, 75, 95, 255) };


                var stripe = GameObject.CreatePrimitive(PrimitiveType.Cube);
                stripe.name = "WallStripe";
                stripe.transform.position = new Vector3(side * 14.7f, 1.5f, lineCenterZ);
                stripe.transform.localScale = new Vector3(0.1f, 0.15f, sceneDepth);
                Destroy(stripe.GetComponent<Collider>());
                stripe.GetComponent<Renderer>().material = new Material(shader)
                {
                    color = SSColorPalette.WithAlpha(SSColorPalette.Accent, 0.3f)
                };
            }


            foreach (float z in new[] { lineCenterZ + halfDepth, lineCenterZ - halfDepth })
            {
                var bw = GameObject.CreatePrimitive(PrimitiveType.Cube);
                bw.name = "EndWall";
                bw.transform.position = new Vector3(0, 5, z);
                bw.transform.localScale = new Vector3(30, 10, 0.5f);
                Destroy(bw.GetComponent<Collider>());
                bw.GetComponent<Renderer>().material =
                    new Material(shader) { color = new Color32(70, 70, 88, 255) };
            }


            var ceiling = GameObject.CreatePrimitive(PrimitiveType.Cube);
            ceiling.name = "Ceiling";
            ceiling.transform.position = new Vector3(0, 10, lineCenterZ);
            ceiling.transform.localScale = new Vector3(30, 0.3f, sceneDepth);
            Destroy(ceiling.GetComponent<Collider>());
            ceiling.GetComponent<Renderer>().material =
                new Material(shader) { color = new Color32(55, 58, 72, 255) };


            Color[] pipeColors =
            {
                new Color32(90, 90, 110, 255),
                new Color32(100, 85, 75, 255),
                SSColorPalette.WithAlpha(SSColorPalette.Primary, 0.5f),
            };
            for (int i = 0; i < 12; i++)
            {
                int side = Random.value > 0.5f ? 1 : -1;
                var pipe = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                pipe.name = $"Pipe_{i}";
                pipe.transform.position = new Vector3(
                    side * Random.Range(12f, 14.5f),
                    Random.Range(4f, 8.5f),
                    lineCenterZ + Random.Range(-halfDepth * 0.7f, halfDepth * 0.7f));
                pipe.transform.localScale = new Vector3(
                    Random.Range(0.12f, 0.25f),
                    Random.Range(2f, 6f),
                    Random.Range(0.12f, 0.25f));
                pipe.transform.rotation = Quaternion.Euler(0, 0, 90);
                Destroy(pipe.GetComponent<Collider>());
                pipe.GetComponent<Renderer>().material =
                    new Material(shader)
                    {
                        color = pipeColors[Random.Range(0, pipeColors.Length)]
                    };
            }


            for (float z = lineCenterZ - halfDepth; z < lineCenterZ + halfDepth; z += 5f)
            {
                var ws = GameObject.CreatePrimitive(PrimitiveType.Cube);
                ws.name = "WarningStripe";
                ws.transform.position = new Vector3(0, 0.01f, z);
                ws.transform.localScale = new Vector3(18, 0.01f, 0.2f);
                Destroy(ws.GetComponent<Collider>());
                ws.GetComponent<Renderer>().material = new Material(shader)
                {
                    color = SSColorPalette.WithAlpha(SSColorPalette.Accent, 0.08f)
                };
            }


            for (float z = lineCenterZ - halfDepth + 3; z < lineCenterZ + halfDepth; z += 5f)
            {

                var pole = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                pole.name = "LampPole";
                pole.transform.position = new Vector3(0, 9.3f, z);
                pole.transform.localScale = new Vector3(0.03f, 0.6f, 0.03f);
                Destroy(pole.GetComponent<Collider>());
                pole.GetComponent<Renderer>().material =
                    new Material(shader) { color = new Color32(90, 90, 100, 255) };


                var head = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                head.name = "LampHead";
                head.transform.position = new Vector3(0, 8.7f, z);
                head.transform.localScale = new Vector3(0.5f, 0.06f, 0.5f);
                Destroy(head.GetComponent<Collider>());
                head.GetComponent<Renderer>().material = new Material(shader)
                {
                    color = SSColorPalette.WithAlpha(SSColorPalette.Accent, 0.6f)
                };


                var lampLight = new GameObject($"LampLight_{z:F0}");
                var lt = lampLight.AddComponent<Light>();
                lt.type = LightType.Point;
                lt.range = 8;
                lt.intensity = 0.4f;
                lt.color = new Color32(255, 240, 210, 255);
                lampLight.transform.position = new Vector3(0, 8.5f, z);
            }


            for (int i = 0; i < 6; i++)
            {
                float side = (i % 2 == 0) ? -1 : 1;
                var equip = GameObject.CreatePrimitive(PrimitiveType.Cube);
                equip.name = "Equipment";
                float h = Random.Range(1f, 2.5f);
                equip.transform.position = new Vector3(
                    side * Random.Range(5f, 10f),
                    h / 2f,
                    lineCenterZ + Random.Range(-halfDepth * 0.6f, halfDepth * 0.6f));
                equip.transform.localScale = new Vector3(
                    Random.Range(1f, 2f), h, Random.Range(1f, 2f));
                Destroy(equip.GetComponent<Collider>());
                Color[] equipColors =
                {
                    SSColorPalette.WithAlpha(SSColorPalette.Primary, 0.4f),
                    new Color32(80, 80, 100, 255),
                    SSColorPalette.WithAlpha(SSColorPalette.Info, 0.3f),
                };
                equip.GetComponent<Renderer>().material = new Material(shader)
                {
                    color = equipColors[Random.Range(0, equipColors.Length)]
                };
            }
        }


        private void SetupLighting()
        {

            var existing = FindObjectOfType<Light>();
            Light dirLight;
            if (existing != null)
                dirLight = existing;
            else
            {
                var lo = new GameObject("DirectionalLight");
                dirLight = lo.AddComponent<Light>();
            }
            dirLight.type = LightType.Directional;
            dirLight.transform.rotation = Quaternion.Euler(45, -30, 0);

            dirLight.color = new Color32(240, 235, 220, 255);
            dirLight.intensity = 1.1f;
            dirLight.shadows = LightShadows.Soft;


            var fillObj = new GameObject("FillLight");
            var fill = fillObj.AddComponent<Light>();
            fill.type = LightType.Point;
            fill.range = 35;
            fill.intensity = 0.6f;
            fill.color = new Color32(210, 220, 240, 255);
            fillObj.transform.position = new Vector3(-10, 5, _lineCenterZ);


            Color[] accentColors = {
                SSColorPalette.Accent, SSColorPalette.Info,
                SSColorPalette.Primary, SSColorPalette.Success
            };
            for (int i = 0; i < 4; i++)
            {
                var pl = new GameObject($"AccentLight_{i}");
                var lt = pl.AddComponent<Light>();
                lt.type = LightType.Point;
                lt.range = 10;
                lt.intensity = 0.3f;
                lt.color = accentColors[i % accentColors.Length];
                float z = _lineCenterZ + Mathf.Lerp(-6, 6, (float)i / 3);
                pl.transform.position = new Vector3(
                    (i % 2 == 0 ? -1 : 1) * 6f, 6f, z);
            }


            RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Flat;
            RenderSettings.ambientLight = new Color32(75, 78, 95, 255);
        }


        private TfQuestion[] GetTestQuestions()
        {
            return new TfQuestion[]
            {
                new() { id="1", question_text="الشمس تدور حول الأرض",
                    is_true=false, source="علوم" },
                new() { id="2", question_text="الماء يتكون من الهيدروجين والأكسجين",
                    is_true=true, source="كيمياء" },
                new() { id="3", question_text="القمر ينير بذاته",
                    is_true=false, source="فلك" },
                new() { id="4", question_text="النباتات تحتاج ضوء الشمس لعملية البناء الضوئي",
                    is_true=true, source="أحياء" },
                new() { id="5", question_text="عدد قارات العالم خمس قارات",
                    is_true=false, source="جغرافيا" },
                new() { id="6", question_text="الحديد يتمدد بالحرارة",
                    is_true=true, source="فيزياء" },
                new() { id="7", question_text="المحيط الأطلسي هو أكبر محيطات العالم",
                    is_true=false, source="جغرافيا" },
                new() { id="8", question_text="جسم الإنسان يحتوي على 206 عظمة",
                    is_true=true, source="أحياء" },
            };
        }

        private Shader GetShader()
        {
            return Shader.Find("Universal Render Pipeline/Lit")
                ?? Shader.Find("Standard")
                ?? Shader.Find("Unlit/Color");
        }
    }
}
