using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using QuantEngine.Core.Interfaces;

namespace QuantEngine.Infrastructure.External
{
    public class NaverFinanceScraper : INaverFinanceScraper
    {
        private readonly HttpClient _httpClient;
        private const string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0 Safari/537.36";
        private const string Referer = "https://finance.naver.com/";

        public NaverFinanceScraper(HttpClient httpClient)
        {
            _httpClient = httpClient;
            // Register CodePages encoding provider to support EUC-KR
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
        }

        private double CleanNumber(string text)
        {
            if (string.IsNullOrWhiteSpace(text)) return 0.0;
            var cleaned = text.Replace(",", "").Replace("+", "").Replace("%", "").Trim();
            return double.TryParse(cleaned, out var result) ? result : 0.0;
        }

        public async Task<string> FetchPriceHistoryAsync(string code, int pages = 3)
        {
            var rows = new List<Dictionary<string, object>>();
            var eucKr = Encoding.GetEncoding("euc-kr");

            for (int page = 1; page <= pages; page++)
            {
                var url = $"https://finance.naver.com/item/sise_day.naver?code={code}&page={page}";
                
                using var request = new HttpRequestMessage(HttpMethod.Get, url);
                request.Headers.Add("User-Agent", UserAgent);
                request.Headers.Add("Referer", Referer);

                var response = await _httpClient.SendAsync(request);
                if (response.StatusCode == System.Net.HttpStatusCode.Forbidden)
                {
                    return JsonSerializer.Serialize(new
                    {
                        status = "CLOUDFLARE_BLOCKED_403",
                        rows = new List<object>(),
                        error = "Cloudflare rejected request (403 Forbidden)",
                        source_url = url
                    });
                }
                response.EnsureSuccessStatusCode();

                var bytes = await response.Content.ReadAsByteArrayAsync();
                var html = eucKr.GetString(bytes);

                // Simple regex parser for table rows
                var trMatches = Regex.Matches(html, @"<tr[^>]*>([\s\S]*?)<\/tr>");
                foreach (Match trMatch in trMatches)
                {
                    var trContent = trMatch.Groups[1].Value;
                    var tdMatches = Regex.Matches(trContent, @"<td[^>]*>([\s\S]*?)<\/td>");
                    if (tdMatches.Count == 7)
                    {
                        var dateText = Regex.Replace(tdMatches[0].Groups[1].Value, @"<[^>]*>", "").Trim();
                        if (string.IsNullOrEmpty(dateText) || !dateText.Contains(".")) continue;

                        rows.Add(new Dictionary<string, object>
                        {
                            { "date", dateText.Replace(".", "-") },
                            { "close", CleanNumber(Regex.Replace(tdMatches[1].Groups[1].Value, @"<[^>]*>", "")) },
                            { "open", CleanNumber(Regex.Replace(tdMatches[3].Groups[1].Value, @"<[^>]*>", "")) },
                            { "high", CleanNumber(Regex.Replace(tdMatches[4].Groups[1].Value, @"<[^>]*>", "")) },
                            { "low", CleanNumber(Regex.Replace(tdMatches[5].Groups[1].Value, @"<[^>]*>", "")) },
                            { "volume", CleanNumber(Regex.Replace(tdMatches[6].Groups[1].Value, @"<[^>]*>", "")) }
                        });
                    }
                }
            }

            if (rows.Count == 0)
            {
                return JsonSerializer.Serialize(new { status = "DATA_MISSING", rows = new List<object>(), source_url = Referer });
            }

            return JsonSerializer.Serialize(new
            {
                status = "OK",
                rows = rows,
                source_url = $"https://finance.naver.com/item/sise_day.naver?code={code}",
                source_as_of = DateTime.UtcNow.AddHours(9).ToString("o")
            });
        }

        public async Task<string> FetchForeignInstitutionFlowAsync(string code, int pages = 2)
        {
            var rows = new List<Dictionary<string, object>>();
            var eucKr = Encoding.GetEncoding("euc-kr");

            for (int page = 1; page <= pages; page++)
            {
                var url = $"https://finance.naver.com/item/frgn.naver?code={code}&page={page}";

                using var request = new HttpRequestMessage(HttpMethod.Get, url);
                request.Headers.Add("User-Agent", UserAgent);
                request.Headers.Add("Referer", Referer);

                var response = await _httpClient.SendAsync(request);
                if (response.StatusCode == System.Net.HttpStatusCode.Forbidden)
                {
                    return JsonSerializer.Serialize(new
                    {
                        status = "CLOUDFLARE_BLOCKED_403",
                        rows = new List<object>(),
                        error = "Cloudflare rejected request (403 Forbidden)",
                        source_url = url
                    });
                }
                response.EnsureSuccessStatusCode();

                var bytes = await response.Content.ReadAsByteArrayAsync();
                var html = eucKr.GetString(bytes);

                var trMatches = Regex.Matches(html, @"<tr[^>]*>([\s\S]*?)<\/tr>");
                foreach (Match trMatch in trMatches)
                {
                    var trContent = trMatch.Groups[1].Value;
                    var tdMatches = Regex.Matches(trContent, @"<td[^>]*>([\s\S]*?)<\/td>");
                    if (tdMatches.Count >= 8)
                    {
                        var dateText = Regex.Replace(tdMatches[0].Groups[1].Value, @"<[^>]*>", "").Trim();
                        if (string.IsNullOrEmpty(dateText) || !dateText.Contains(".")) continue;

                        rows.Add(new Dictionary<string, object>
                        {
                            { "date", dateText.Replace(".", "-") },
                            { "close", CleanNumber(Regex.Replace(tdMatches[1].Groups[1].Value, @"<[^>]*>", "")) },
                            { "inst_net", CleanNumber(Regex.Replace(tdMatches[5].Groups[1].Value, @"<[^>]*>", "")) },
                            { "frgn_net", CleanNumber(Regex.Replace(tdMatches[6].Groups[1].Value, @"<[^>]*>", "")) }
                        });
                    }
                }
            }

            if (rows.Count == 0)
            {
                return JsonSerializer.Serialize(new { status = "DATA_MISSING", rows = new List<object>() });
            }

            return JsonSerializer.Serialize(new
            {
                status = "OK",
                rows = rows,
                source_url = $"https://finance.naver.com/item/frgn.naver?code={code}",
                source_as_of = DateTime.UtcNow.AddHours(9).ToString("o")
            });
        }
    }
}
