using System;
using System.IO;
using UnityEditor;
using UnityEngine;

namespace Streamingle.Editor
{
    public sealed class AICameraABRenderWindow : EditorWindow
    {
        private string candidateADirectory = string.Empty;
        private string candidateBDirectory = string.Empty;
        private string outputRoot = string.Empty;
        private int startFrame;
        private int endFrameExclusive = 1;
        private AICameraABRenderCodec codec =
            AICameraABRenderCodec.MP4;
        private int width = 1920;
        private int height = 1080;
        private Vector2 scrollPosition;

        [MenuItem("Tools/Streamingle/Timeline/Render AI Camera A-B")]
        public static void Open()
        {
            GetWindow<AICameraABRenderWindow>(
                "AI Camera A-B Render");
        }

        private void OnEnable()
        {
            if (string.IsNullOrWhiteSpace(outputRoot))
            {
                outputRoot = Path.GetFullPath(Path.Combine(
                    Application.dataPath,
                    "..",
                    "Recordings",
                    "CWAI_AB"));
            }
        }

        private void OnInspectorUpdate()
        {
            Repaint();
        }

        private void OnGUI()
        {
            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
            EditorGUILayout.LabelField(
                "AI Camera A-B Movie Render",
                EditorStyles.boldLabel);
            EditorGUILayout.LabelField(
                "Renders two generated camera candidates against the same " +
                "saved Scene, Timeline frame range, and Timeline audio.",
                EditorStyles.wordWrappedLabel);
            EditorGUILayout.Space();

            DrawFolderField(
                "Candidate A",
                ref candidateADirectory,
                "Select generated camera candidate A");
            DrawFolderField(
                "Candidate B",
                ref candidateBDirectory,
                "Select generated camera candidate B");
            DrawFolderField(
                "Output Root",
                ref outputRoot,
                "Select A-B movie output directory");

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Frame Range", EditorStyles.boldLabel);
            startFrame = EditorGUILayout.IntField(
                "Start Frame",
                startFrame);
            endFrameExclusive = EditorGUILayout.IntField(
                "End Frame (Exclusive)",
                endFrameExclusive);

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Movie", EditorStyles.boldLabel);
            codec = (AICameraABRenderCodec)EditorGUILayout.EnumPopup(
                "Codec",
                codec);
            width = EditorGUILayout.IntField("Width", width);
            height = EditorGUILayout.IntField("Height", height);
            EditorGUILayout.HelpBox(
                "MP4 uses H.264 and requires even dimensions. WebM uses VP8. " +
                "Both candidates use MainCamera and include Timeline audio.",
                MessageType.Info);

            EditorGUILayout.Space();
            DrawActiveJob();
            EditorGUILayout.Space();

            var hasActive = AICameraABRenderRunner.TryGetActiveStatus(
                out _,
                out var phase,
                out _);
            var nonTerminalJob =
                hasActive &&
                !AICameraABRenderUtility.IsTerminalPhase(phase);
            using (new EditorGUI.DisabledScope(nonTerminalJob))
            {
                if (GUILayout.Button("Start A-B Render", GUILayout.Height(30)))
                {
                    StartRender();
                }
            }

            EditorGUILayout.EndScrollView();
        }

        private void DrawActiveJob()
        {
            if (!AICameraABRenderRunner.TryGetActiveStatus(
                    out var jobId,
                    out var phase,
                    out var manifestPath))
            {
                EditorGUILayout.LabelField("No active A-B render job.");
                return;
            }

            EditorGUILayout.LabelField("Current Job", EditorStyles.boldLabel);
            EditorGUILayout.SelectableLabel(
                jobId,
                EditorStyles.textField,
                GUILayout.Height(EditorGUIUtility.singleLineHeight));
            EditorGUILayout.LabelField("Phase", phase);
            EditorGUILayout.LabelField(
                "Manifest",
                manifestPath,
                EditorStyles.wordWrappedLabel);

            using (new EditorGUILayout.HorizontalScope())
            {
                if (GUILayout.Button("Reveal Manifest") &&
                    !string.IsNullOrWhiteSpace(manifestPath))
                {
                    EditorUtility.RevealInFinder(manifestPath);
                }

                using (new EditorGUI.DisabledScope(
                           AICameraABRenderUtility.IsTerminalPhase(phase)))
                {
                    if (GUILayout.Button("Cancel"))
                    {
                        AICameraABRenderRunner.CancelABRenderForCli(jobId);
                    }
                }
            }
        }

        private void StartRender()
        {
            try
            {
                var request = new AICameraABRenderRequest
                {
                    candidateADirectory = candidateADirectory,
                    candidateBDirectory = candidateBDirectory,
                    outputRoot = outputRoot,
                    startFrame = startFrame,
                    endFrameExclusive = endFrameExclusive,
                    codec = codec,
                    width = width,
                    height = height
                };
                var started = AICameraABRenderRunner.Start(request);
                Debug.Log(
                    $"CW-AI A/B render started. Manifest: " +
                    $"{started.manifestPath}");
            }
            catch (Exception exception)
            {
                Debug.LogException(exception);
                EditorUtility.DisplayDialog(
                    "Unable to start A-B render",
                    exception.Message,
                    "OK");
            }
        }

        private static void DrawFolderField(
            string label,
            ref string value,
            string dialogTitle)
        {
            using (new EditorGUILayout.HorizontalScope())
            {
                value = EditorGUILayout.TextField(label, value);
                if (GUILayout.Button("Browse", GUILayout.Width(70)))
                {
                    var initialDirectory = Directory.Exists(value)
                        ? value
                        : Directory.GetParent(Application.dataPath)?.FullName ??
                          string.Empty;
                    var selected = EditorUtility.OpenFolderPanel(
                        dialogTitle,
                        initialDirectory,
                        string.Empty);
                    if (!string.IsNullOrWhiteSpace(selected))
                    {
                        value = selected;
                    }
                }
            }
        }
    }
}
