// Copyright (c) 2025 TerraByte Inc.
//
// A modal editor window that displays pull conflicts and allows the user
// to select files to reset before proceeding.

using System;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Terra.Arbitrator.Services;
using System.Collections.Generic;

namespace Terra.Arbitrator.GUI
{
    public class ConflictResolutionWindow : EditorWindow
    {
        private List<string> _conflictingFiles;
        private List<bool> _filesToReset;
        private Vector2 _scrollPosition;
        private Action<List<string>> _onCloseCallback;
        private bool _callbackInvoked;

        /// <summary>
        /// Shows a modal window to display pull conflicts and get user action.
        /// </summary>
        /// <param name="conflictingFiles">The list of files that have conflicts.</param>
        /// <param name="onCloseCallback">A callback that provides the list of files the user selected to reset. If the user cancels, the list will be null.</param>
        public static void ShowWindow(List<string> conflictingFiles, Action<List<string>> onCloseCallback)
        {
            var window = GetWindow<ConflictResolutionWindow>(true, "Pull Conflicts Detected", true);
            window.minSize = new Vector2(600, 400);
            window._conflictingFiles = conflictingFiles;
            window._filesToReset = new List<bool>(new bool[conflictingFiles.Count]); // Initialize all to false
            window._onCloseCallback = onCloseCallback;
            window._callbackInvoked = false;
            window.ShowModalUtility();
        }

        private void OnGUI()
        {
            EditorGUILayout.HelpBox("A pull would result in conflicts with your local changes. To proceed with a clean pull, you must reset your local changes for the conflicting files listed below.", MessageType.Warning);
            
            EditorGUILayout.LabelField("Conflicting Files:", EditorStyles.boldLabel);

            _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, EditorStyles.helpBox);
            for (var i = 0; i < _conflictingFiles.Count; i++)
            {
                EditorGUILayout.BeginHorizontal();
                _filesToReset[i] = EditorGUILayout.Toggle(_filesToReset[i], GUILayout.Width(20));
                EditorGUILayout.LabelField(_conflictingFiles[i]);
                if (GUILayout.Button("Local Diff", GUILayout.Width(100)))
                {
                    // Find the GitChange object to pass to the diff service.
                    var change = GitService.GetChangeForFile(_conflictingFiles[i]);
                    if (change != null)
                    {
                        GitService.LaunchExternalDiff(change);
                    }
                    else
                    {
                        Debug.LogWarning($"Could not get status for {_conflictingFiles[i]} to launch diff.");
                    }
                }
                EditorGUILayout.EndHorizontal();
            }
            EditorGUILayout.EndScrollView();

            EditorGUILayout.Space();

            DrawActionButtons();
        }

        private void DrawActionButtons()
        {
            var selectedCount = _filesToReset.Count(selected => selected);
            var canReset = selectedCount > 0;

            EditorGUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();

            EditorGUI.BeginDisabledGroup(!canReset);
            if (GUILayout.Button($"Reset {selectedCount} Selected File(s)", GUILayout.Height(30), GUILayout.Width(200)))
            {
                var filesToResetPaths = new List<string>();
                for (var i = 0; i < _conflictingFiles.Count; i++)
                {
                    if (_filesToReset[i])
                    {
                        filesToResetPaths.Add(_conflictingFiles[i]);
                    }
                }
                _callbackInvoked = true;
                _onCloseCallback?.Invoke(filesToResetPaths);
                Close();
            }
            EditorGUI.EndDisabledGroup();

            if (GUILayout.Button(new GUIContent("Pull Anyway", "This will perform the pull, leaving merge conflicts in your local files for you to resolve."), GUILayout.Height(30)))
            {
                _callbackInvoked = true;
                _onCloseCallback?.Invoke(new List<string>());
                Close();
            }
            
            if (GUILayout.Button("Cancel", GUILayout.Height(30)))
            {
                Close();
            }

            EditorGUILayout.EndHorizontal();
        }

        private void OnDestroy()
        {
            if (!_callbackInvoked)
            {
                _onCloseCallback?.Invoke(null);
            }
        }
    }
}
