using System;
using System.Linq;
using UnityEngine;
using LLM.Editor.Core;
using LLM.Editor.Data;
using System.Threading;
using LLM.Editor.Commands;
using System.Threading.Tasks;
using System.Collections.Generic;
using LLM.Editor.Tests.Integration;

namespace LLM.Editor.Client
{
    /// <summary>
    /// A mock client that simulates an LLM response for testing purposes.
    /// It now discovers and runs test cases from C# classes that implement IDummyTestCase.
    /// </summary>
    public class DummyApiClient : ILlmApiClient
    {
        private static List<IDummyTestCase> _testCases;
        private static bool _testCasesLoaded;
        
        private IDummyTestCase _activeTestCase;
        private int _activeResponseStep;

        public static List<IDummyTestCase> GetTestCases()
        {
            if (!_testCasesLoaded)
            {
                DiscoverTestCases();
            }
            return _testCases;
        }

        private static void DiscoverTestCases()
        {
            _testCases = new List<IDummyTestCase>();
            var testCaseType = typeof(IDummyTestCase);
            
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assembly in assemblies)
            {
                try
                {
                    var types = assembly.GetTypes();
                    foreach (var type in types)
                    {
                        if (testCaseType.IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract)
                        {
                            var instance = (IDummyTestCase)Activator.CreateInstance(type);
                            _testCases.Add(instance);
                        }
                    }
                }
                catch (Exception e)
                {
                    Debug.LogWarning($"[DummyApiClient] Could not inspect assembly {assembly.FullName} for test cases: {e.Message}");
                }
            }
            
            _testCases = _testCases.OrderBy(tc => tc.TriggerPhrase).ToList();
            _testCasesLoaded = true;
            Debug.Log($"[DummyApiClient] Discovered {_testCases.Count} C# test cases.");
        }

        public Task<bool> Initialize()
        {
            // Dummy client needs no async initialization.
            return Task.FromResult(true);
        }

        public async Task SendPrompt(string prompt, List<UnityEngine.Object> stagedContext, CancellationToken cancellationToken = default)
        {
            if (!_testCasesLoaded) DiscoverTestCases();

            _activeTestCase = _testCases.FirstOrDefault(
                c => prompt.Equals(c.TriggerPhrase, StringComparison.Ordinal)
            );

            // Simulate network delay
            await Task.Delay(500, cancellationToken);
            if (cancellationToken.IsCancellationRequested) return;

            if (_activeTestCase != null)
            {
                Debug.Log($"[DummyApiClient] Triggered test case for: '{_activeTestCase.TriggerPhrase}'");
                _activeResponseStep = 0;
                ExecuteStep();
            }
            else
            {
                DisplayError("No test case was triggered by your prompt.");
            }
        }

        public async Task SendFollowUp(string detailedContext, CancellationToken cancellationToken = default)
        {
            // Simulate network delay
            await Task.Delay(500, cancellationToken);
            if (cancellationToken.IsCancellationRequested) return;
            
            if (_activeTestCase != null)
            {
                _activeResponseStep++;
                Debug.Log($"[DummyApiClient] Executing follow-up step #{_activeResponseStep + 1} for test case: '{_activeTestCase.TriggerPhrase}'");
                ExecuteStep();
            }
            else
            {
                Debug.LogWarning("[DummyApiClient] Received a follow-up call, but no active test case was found.");
                DisplayError("No active test case for follow-up.");
            }
        }

        public string GetAuthToken()
        {
            return "dummy-token";
        }
        
        private void ExecuteStep()
        {
            var commandSteps = _activeTestCase?.GetCommandSteps();
            if (commandSteps == null || _activeResponseStep >= commandSteps.Count)
            {
                Debug.Log("[DummyApiClient] Test case finished or has no more steps.");
                _activeTestCase = null; // End the test case
                return;
            }
            
            var commands = commandSteps[_activeResponseStep];
            CommandExecutor.SetQueue(commands, _activeTestCase.TriggerPhrase);
        }

        private void DisplayError(string message)
        {
            var commandData = new CommandData
            {
                commandName = nameof(DisplayMessageCommand),
                jsonData = new Newtonsoft.Json.Linq.JObject
                {
                    ["outcome"] = "Error",
                    ["message"] = $"[Dummy Client Error] {message}"
                }
            };
            CommandExecutor.SetQueue(new List<CommandData> { commandData }, "Error");
        }
    }
}