using System;
using System.Collections.Generic;
using System.Linq;
using eagle.Notifications;
using Net.Eagle0.Eagle.Views;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

namespace eagle {
    using ProvinceId = Int32;

    public class NotificationPanel : PopupPanelController {
        public Button dismissAllButton;
        public TMP_Text dismissOneButtonText;
        public GameObject spacer;

        private readonly Queue<Notification> _notes = new();

        // Incremented when DismissAll is clicked; pending AddNote calls check this
        // to skip adding if a dismiss happened since they were enqueued
        private int _dismissGeneration = 0;

        private void SetPopupInfos() {
            PopupInfos = _notes.Select(note => new PopupInfo {
                                   titleText = note.Title,
                                   mainText = note.Text,
                                   mainTextLlmId = note.LlmId,
                                   affectedProvinceIds = note.ProvinceIds,
                                   displayedHeroes = note.DisplayedHeroes
                               })
                                 .ToList();

            SetUpPanel();

            // If there are no images, add a spacer to the panel
            spacer.gameObject.SetActive(!imagesAndNamesContainer.gameObject.activeSelf);
            if (PopupInfos.Count == 1) {
                dismissAllButton.gameObject.SetActive(false);
                dismissOneButtonText.text = "Done";
            } else {
                dismissAllButton.gameObject.SetActive(true);
                dismissOneButtonText.text = "Dismiss";
            }
        }

        // Compare hero lists by ID since HeroView is a protobuf message with reference equality
        private static bool HeroListsMatch(List<HeroView> a, List<HeroView> b) {
            if (a == null && b == null) return true;
            if (a == null || b == null) return false;
            if (a.Count != b.Count) return false;
            return a.Select(h => h.Id).SequenceEqual(b.Select(h => h.Id));
        }

        public void AddNote(
                string title,
                string text,
                string llmId,
                List<ProvinceId> provinceIds,
                List<HeroView> displayedHeroes) {
            // Capture current generation - if DismissAll is clicked before this executes,
            // we'll skip adding the note
            var capturedGeneration = _dismissGeneration;
            MainQueue.Q.Enqueue(() => {
                // Skip if DismissAll was clicked since this was enqueued
                if (capturedGeneration != _dismissGeneration) return;

                var existingNote = _notes.FirstOrDefault(
                        n => n.Title == title &&
                             HeroListsMatch(n.DisplayedHeroes, displayedHeroes));

                if (existingNote == null) {
                    _notes.Enqueue(new Notification(
                            title: title,
                            text: text,
                            llmId: llmId,
                            provinceIds: provinceIds,
                            displayedHeroes: displayedHeroes));
                } else {
                    existingNote.Append(text, provinceIds);
                }
                SetPopupInfos();
            });
        }

        public void DismissButtonClicked() {
            _notes.Dequeue();
            SetPopupInfos();
        }

        public void DismissAllClicked() {
            // Increment generation immediately so pending AddNote calls will skip
            _dismissGeneration++;
            _notes.Clear();
            SetPopupInfos();
        }
    }
}