using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace WikipediaRagWinForms.Services
{
    public class WikiSummary
    {
        public string Title { get; set; }
        public string Extract { get; set; }
        public string WikidataId { get; set; }
    }


    public class WikipediaOnlineClient
    {
        private readonly HttpClient _http;
        private static readonly Dictionary<string, string> _summaryCache =
    new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

        public WikipediaOnlineClient()
        {
            _http = new HttpClient();
            _http.DefaultRequestHeaders.Add(
                "User-Agent",
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
            );
        }

        // Nutzt den übergebenen Suchbegriff 1:1 in der Wikipedia-Suche.
        public async Task<string> SearchAsync(string query)
        {
            if (string.IsNullOrWhiteSpace(query))
                return "";

            // Entfernt Anführungszeichen, typografische Quotes, Apostrophe
            query = query.Trim().Trim('"', '“', '”', '\'');

            try
            {
                using (var client = new HttpClient())
                {
                    // ----- 1) DE-Suche -----
                    string urlDe =
                        "https://de.wikipedia.org/w/api.php?action=query&list=search&srinfo=suggestion&format=json&utf8=1&srsearch="
                        + Uri.EscapeDataString(query);

                    string jsonDe = await client.GetStringAsync(urlDe);
                    var rootDe = JObject.Parse(jsonDe);

                    // Trefferliste
                    var listDe = rootDe["query"]?["search"]?.ToList();
                    if (listDe != null && listDe.Count > 0)
                    {
                        string best = PickBestTitle(listDe);
                        if (!string.IsNullOrWhiteSpace(best))
                            return best;
                    }

                    // Vorschlag
                    string suggestion = (string)rootDe["query"]?["searchinfo"]?["suggestion"];
                    if (!string.IsNullOrWhiteSpace(suggestion))
                        return suggestion;

                    // ----- 2) EN-Fallback -----
                    string urlEn =
                        "https://en.wikipedia.org/w/api.php?action=query&list=search&format=json&utf8=1&srsearch="
                        + Uri.EscapeDataString(query);

                    string jsonEn = await client.GetStringAsync(urlEn);
                    var rootEn = JObject.Parse(jsonEn);

                    var listEn = rootEn["query"]?["search"]?.ToList();
                    if (listEn != null && listEn.Count > 0)
                    {
                        string best = PickBestTitle(listEn);
                        if (!string.IsNullOrWhiteSpace(best))
                            return best;
                    }
                }
            }
            catch
            {
            }

            // 3) Fallback
            return query;            
        }


        // Kurz-Zusammenfassung (Summary) laden // Cache Version
        public async Task<string> GetSummaryAsync(string title)
        {
            if (_summaryCache.TryGetValue(title, out var cached))
                return cached;

            string url = "https://de.wikipedia.org/api/rest_v1/page/summary/" +
                         Uri.EscapeDataString(title);

            try
            {
                // selben HttpClient verwenden → User-Agent bleibt gesetzt
                string json = await _http.GetStringAsync(url);
                var obj = Newtonsoft.Json.Linq.JObject.Parse(json);

                string extract = (string)obj["extract"] ?? "";

                _summaryCache[title] = extract;

                return extract;
            }
            catch
            {
                return "";
            }

        }

        public async Task<string> GetFullExtractAsync(string title)
        {
            string url =
                "https://de.wikipedia.org/w/api.php?action=query&prop=extracts&explaintext=1&format=json&redirects=1&titles="
                + Uri.EscapeDataString(title);

            try
            {
                string json = await _http.GetStringAsync(url);
                var root = JObject.Parse(json);

                var pages = root["query"]?["pages"];
                if (pages != null)
                {
                    foreach (var p in pages.Children())
                    {
                        string extract = (string)p.First["extract"];
                        if (!string.IsNullOrWhiteSpace(extract))
                            return extract;
                    }
                }
            }
            catch
            {
            }

            return "";
        }

        public async Task<WikiSummary> GetSummaryAsyncExtended(string title)
        {
            // NUR Deutsche Wikipedia benutzen – DE liefert stabilste Q-ID
            string url =
                $"https://de.wikipedia.org/api/rest_v1/page/summary/{Uri.EscapeDataString(title)}";

            try
            {
                string json = await _http.GetStringAsync(url);
                var obj = JObject.Parse(json);

                return new WikiSummary
                {
                    Title = (string)obj["title"] ?? "",
                    Extract = (string)obj["extract"] ?? "",
                    WikidataId = (string)obj["wikibase_item"] ?? ""
                };
            }
            catch
            {
                return new WikiSummary
                {
                    Title = title,
                    Extract = "",
                    WikidataId = ""
                };
            }
        }

        private string PickBestTitle(IEnumerable<JToken> items)
        {
            // Prioritäten:
            // 1) Vollständige Namensmatch (z.B. "Friedrich Merz")
            // 2) Personenartikel ("<Name> <Nachname>")
            // 3) Keine Klammern oder einfache Klammern
            // 4) Kürzester Titel gewinnt

            var candidates = new List<string>();

            foreach (var item in items)
            {
                string t = (string)item["title"];
                if (string.IsNullOrWhiteSpace(t))
                    continue;

                candidates.Add(t);
            }

            if (candidates.Count == 0)
                return "";

            string q = candidates.First(); // Default

            // Exakter Match
            string exact = candidates
                .FirstOrDefault(c => c.Equals(q, StringComparison.OrdinalIgnoreCase));
            if (!string.IsNullOrWhiteSpace(exact))
                return exact;

            // Personenartikel: "Vorname Nachname"
            var person = candidates.FirstOrDefault(c => c.Contains(" "));
            if (!string.IsNullOrWhiteSpace(person))
                return person;

            // Kürzesten Titel bevorzugen
            return candidates.OrderBy(c => c.Length).First();
        }
    }
}


