using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
using ReAct_PME.Domain;
using ReAct_PME.WebUI.ServicesUI;
using System.Net.Http.Json;

namespace ReAct_PME.WebUI.Pages.ChatRoom
{
    public partial class ChatRoom_base : ComponentBase
    {
        [Parameter] public int TypeLLM { get; set; }
        [Parameter] public string? ConversationId { get; set; }

        [Inject] public HttpClient Http { get; set; } = default!;
        [Inject] private ReAct_PME.WebUI.ServicesUI.AuthService AuthService { get; set; } = default!;
        [Inject] private ReAct_PME.WebUI.ServicesUI.ApiService ApiService { get; set; } = default!;
        [Inject] private AuthenticationStateProvider AuthenticationStateProvider { get; set; } = default!;
        [Inject] private NavigationManager Navigation { get; set; } = default!;
        [Inject] private IToastService ToastService { get; set; } = default!;
        [Inject] private IJSRuntime JSRuntime { get; set; } = default!;

        public class UploadedDoc
        {
            public string FileName { get; set; } = "";
            public byte[] Bytes { get; set; } = Array.Empty<byte>();
        }

        public List<UploadedDoc> UploadedDocuments { get; set; } = new();

        // État de l'UI
        public List<ConversationDto> Conversations { get; set; } = new();
        public ConversationDto? SelectedConversation { get; set; }
        public string SelectedConversationId { get; set; } = "";
        public List<MessageDto> Messages { get; set; } = new();
        private bool IsWithHistorique { get; set; }
        private bool isTyping { get; set; } = false;
        private bool isDisabled { get; set; } = false;

        public string CurrentInput { get; set; } = "";
        public int SelectedAgentType { get; set; } = 1; // Agent par défaut sélectionné
        public string ClientId { get; set; } = ""; // ID Client pour AUDIT

        // Options
        public List<string> RagDomains { get; set; } = new();
        public List<string> OllamaModels { get; set; } = new();
        public string SelectedModel { get; set; } = "";
        public string SelectedMode { get; set; } = "";
        public string SelectedDomain { get; set; } = "";
        private bool IsNewConversation = false;
        public bool hiddenDomain = true;

        protected override async Task OnParametersSetAsync()
        {
            // Configuration selon le type de LLM
            if (TypeLLM == 0)
            {
                // Mode Home - pas de configuration particulière
                return;
            }

            await LoadConversations();
            if (TypeLLM == 1)
            {
                SelectedMode = "llm";
                IsWithHistorique = true;
                hiddenDomain = true;
            }
            else if (TypeLLM == 2)
            {
                SelectedMode = "rag";
                IsWithHistorique = false;
                hiddenDomain = false;
                await LoadRagDomains();
                if (RagDomains.Any())
                    SelectedDomain = RagDomains[0];
            }
            else if (TypeLLM == 3)
            {
                SelectedMode = "audit";
                IsWithHistorique = false;
                hiddenDomain = true;
                SelectedDomain = "comptabilite"; // Domaine fixe pour AUDIT
            }
            else if (TypeLLM == 4)
            {
                SelectedMode = "image";
                IsWithHistorique = false;
                hiddenDomain = true;
            }
            else
            {
                SelectedMode = "llm";
                IsWithHistorique = true;
                hiddenDomain = true;
            }

            if (!string.IsNullOrEmpty(ConversationId))
            {
                SelectConversation(ConversationId);
            }
            else
            {
                Console.WriteLine("No conversationId in URL");
            }

            StateHasChanged();
        }

        protected override async Task OnInitializedAsync()
        {
            #region Vérification si utilisateur est connecté et s'il a les droits
            var tok = await PagesInitializer.VerifConnexionAndRules(
                AuthenticationStateProvider,
                Navigation,
                Http,
                ToastService,
                "/api/ChatRoom/llm/test"
            );

            if (tok == null || tok.Length == 0)
                return;
            else
                AuthService.SetToken(tok);
            #endregion
        }

        private async Task UploadDocuments(InputFileChangeEventArgs e)
        {
            foreach (var file in e.GetMultipleFiles())
            {
                using var stream = file.OpenReadStream(maxAllowedSize: 20 * 1024 * 1024); // 20 Mo
                using var ms = new MemoryStream();
                await stream.CopyToAsync(ms);

                UploadedDocuments.Add(new UploadedDoc
                {
                    FileName = file.Name,
                    Bytes = ms.ToArray()
                });
            }

            StateHasChanged();
        }

        private void RemoveDocument(UploadedDoc doc)
        {
            UploadedDocuments.Remove(doc);
            StateHasChanged();
        }

        private async Task LoadConversations()
        {
            if (string.IsNullOrEmpty(ConversationId))
                return;

            var oneConversation = await Http.GetFromJsonAsync<ConversationDto>($"/api/ChatRoom/conversation/{ConversationId}")
                            ?? new();

            Conversations = new();
            Conversations.Add(oneConversation);

            StateHasChanged();
        }

        private async Task LoadRagDomains()
        {
            RagDomains = await Http.GetFromJsonAsync<List<string>>("/api/ChatRoom/rag/listeDomaines")
                         ?? new();
        }

        private async Task LoadOllamaModels()
        {
            OllamaModels = await Http.GetFromJsonAsync<List<string>>("/api/ChatRoom/ollama/models")
                           ?? new();

            if (OllamaModels.Count > 0)
                SelectedModel = OllamaModels[0];
        }

        public void CreateConversation()
        {
            ConversationDto newConversation = new();

            if (newConversation != null)
            {
                IsNewConversation = true;
                Conversations.Add(newConversation);
                SelectConversation(newConversation.Id);
            }
        }

        public void SelectConversation(string id)
        {
            SelectedConversationId = id;
            SelectedConversation = Conversations.Where(c => c.Id == id).FirstOrDefault();
            Messages = SelectedConversation?.Messages.OrderBy(m => m.CreatedAt).ToList() ?? new();
            StateHasChanged();
        }

        // Méthode pour envoyer un message depuis la page Home
        private async Task SendMessageFromHome()
        {
            if (string.IsNullOrWhiteSpace(CurrentInput) && !UploadedDocuments.Any())
                return;

            // Vérification de l'ID Client pour AUDIT
            if (SelectedAgentType == 3 && string.IsNullOrWhiteSpace(ClientId))
            {
                ToastService.ShowWarning("Veuillez saisir l'ID Client pour l'audit");
                return;
            }

            try
            {
                isDisabled = true;
                isTyping = true;
                StateHasChanged();

                // Ajoute le message utilisateur dans l'UI
                var userMsg = new MessageDto
                {
                    IsUser = true,
                    Text = CurrentInput
                };
                Messages.Add(userMsg);

                var newConversationId = Guid.NewGuid().ToString();

                // Déterminer le mode selon l'agent sélectionné
                string mode = SelectedAgentType switch
                {
                    1 => "LLM",
                    2 => "RAG",
                    3 => "AUDIT",
                    4 => "IMAGE",
                    _ => "LLM"
                };

                // Pour le mode RAG, charger les domaines si nécessaire
                string domain = "";
                if (SelectedAgentType == 2)
                {
                    if (!RagDomains.Any())
                        await LoadRagDomains();
                    domain = !string.IsNullOrEmpty(SelectedDomain) ? SelectedDomain : (RagDomains.Any() ? RagDomains[0] : "");
                }
                else if (SelectedAgentType == 3)
                {
                    domain = "comptabilite"; // Domaine fixe pour AUDIT
                }

                var payload = new SendMessageRequest
                {
                    ConversationId = newConversationId,
                    IsNewConversation = true,
                    IdWorkForce = AuthService!.ID!,
                    Mode = mode,
                    Domain = domain,
                    Documents64 = UploadedDocuments.Select(d => Convert.ToBase64String(d.Bytes)).ToList(),
                    Documents = UploadedDocuments.Select(d => d.FileName).ToList(),
                    Role = "user",
                    Text = CurrentInput,
                    Context = ""
                };

                CurrentInput = "";

                var assistantMsg = await ApiService.EnvoiRequete<MessageDto>("/api/ChatRoom/sendMessage", payload);

                isTyping = false;
                isDisabled = false;

                if (assistantMsg != null)
                {
                    Messages.Add(assistantMsg);

                    // Navigation vers la conversation créée avec le type d'agent sélectionné
                    Navigation.NavigateTo($"/chatroom_base/{SelectedAgentType}/{newConversationId}");
                }

                UploadedDocuments.Clear();
                StateHasChanged();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                isTyping = false;
                isDisabled = false;
                ToastService.ShowError($"Erreur lors de l'envoi du message : {ex.Message}");
                StateHasChanged();
            }
        }

        public async Task SendMessage()
        {
            try
            {
                if (string.IsNullOrWhiteSpace(CurrentInput) || SelectedConversation == null)
                {
                    // Si on est en mode TypeLLM > 0 mais sans conversation, on la crée
                    if (TypeLLM > 0 && !string.IsNullOrWhiteSpace(CurrentInput))
                    {
                        CreateConversation();
                        if (SelectedConversation == null)
                            return;
                    }
                    else
                    {
                        return;
                    }
                }

                // Vérification de l'ID Client pour AUDIT
                if (TypeLLM == 3 && string.IsNullOrWhiteSpace(ClientId))
                {
                    ToastService.ShowWarning("Veuillez saisir l'ID Client pour l'audit");
                    return;
                }

                isTyping = true;
                StateHasChanged();

                // Ajoute ton message dans l'UI immédiatement
                var userMsg = new MessageDto
                {
                    IsUser = true,
                    Text = CurrentInput
                };
                Messages.Add(userMsg);

                var payload = new SendMessageRequest
                {
                    ConversationId = IsNewConversation ? Guid.NewGuid().ToString() : SelectedConversation.Id,
                    IsNewConversation = IsNewConversation,
                    IdWorkForce = AuthService!.ID!,
                    Mode = SelectedMode.ToUpper(),
                    Domain = SelectedDomain,
                    Documents64 = UploadedDocuments.Select(d => Convert.ToBase64String(d.Bytes)).ToList(),
                    Documents = UploadedDocuments.Select(d => d.FileName).ToList(),
                    Role = "user",
                    Text = CurrentInput,
                    Context = IsWithHistorique ? string.Join("\n ", Messages.Select(m => m.Text)) : ""
                };

                CurrentInput = "";

                var assistantMsg = await ApiService.EnvoiRequete<MessageDto>("/api/ChatRoom/sendMessage", payload);

                isTyping = false;

                if (assistantMsg != null)
                {
                    Messages.Add(assistantMsg);

                    if (IsNewConversation)
                    {
                        // Met à jour la liste des conversations
                        await LoadConversations();
                        SelectConversation(payload.ConversationId);
                        IsNewConversation = false;

                        // Mettre à jour l'URL pour inclure l'ID de la conversation
                        Navigation.NavigateTo($"/chatroom_base/{TypeLLM}/{payload.ConversationId}", false);
                    }
                }

                UploadedDocuments.Clear();
                StateHasChanged();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                isTyping = false;
                StateHasChanged();
            }
        }

        private async Task HandleKeyPress(KeyboardEventArgs e)
        {
            if (e.Key == "Enter" && !e.ShiftKey)
            {
                await SendMessage();
            }
        }

        private void GoBack()
        {
            Navigation.NavigateTo("/chatroom_base/0");
        }

        private void ToggleHistory()
        {
            IsWithHistorique = !IsWithHistorique;
            ToastService.ShowInfo(IsWithHistorique ? "Historique activé" : "Historique désactivé");
        }

        private async Task CopyMessage(string text)
        {
            try
            {
                await JSRuntime.InvokeVoidAsync("navigator.clipboard.writeText", text);
                ToastService.ShowSuccess("Message copié !");
            }
            catch (Exception)
            {
                ToastService.ShowWarning("Impossible de copier le message");
            }
        }

        private void RecordVoice()
        {
            ToastService.ShowInfo("Fonctionnalité d'enregistrement vocal en cours de développement");
        }

        private string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB" };
            double len = bytes;
            int order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len = len / 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }

        private async Task SelectAgent(int agentId)
        {
            SelectedAgentType = agentId;

            if (agentId == 2 && !RagDomains.Any())
            {
                await LoadRagDomains();
                if (RagDomains.Any())
                    SelectedDomain = RagDomains[0];
            }
            else if (agentId == 3)
            {
                SelectedDomain = "compta"; // Domaine fixe pour AUDIT
            }

            StateHasChanged();
        }

        private async Task HandleFileSelection(InputFileChangeEventArgs e)
        {
            await UploadDocuments(e);
        }

        private async Task OnHomeTextareaInput()
        {
            await JSRuntime.InvokeVoidAsync("autoResizeTextarea", "homeTextarea");
        }

        private async Task OnChatroomTextareaInput()
        {
            await JSRuntime.InvokeVoidAsync("autoResizeTextarea", "chatroomTextarea");
        }

        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                try
                {
                    if (TypeLLM == 0)
                    {
                        await JSRuntime.InvokeVoidAsync("setupTextareaAutoResize", "homeTextarea");
                    }
                    else
                    {
                        await JSRuntime.InvokeVoidAsync("setupTextareaAutoResize", "chatroomTextarea");
                    }
                }
                catch
                {
                }
            }
        }
    }
}