using JSMR.Application.Enums;
using JSMR.Domain.ValueObjects;
using JSMR.Infrastructure.Http;
using System.Globalization;
using System.Text.RegularExpressions;

namespace JSMR.Infrastructure.Scanning;

public partial class EnglishVoiceWorksScanner(IHtmlLoader loader) : VoiceWorksScanner(loader)
{
    [GeneratedRegex(@"Release date:&nbsp;(.*?)[/](\d{1,2})[/](\d{4})", RegexOptions.IgnoreCase, "en-US")]
    private static partial Regex SalesDateRegex();

    [GeneratedRegex(@"^(Early|Middle|Late)\s(.*?)\s(\d{4})", RegexOptions.IgnoreCase, "en-US")]
    private static partial Regex EstimatedDateRegex();

    protected override Locale Locale => Locale.English;

    protected override SupportedLanguage[] SupportedLanguages =>
    [
        SupportedLanguage.Japanese,
        SupportedLanguage.English,
        SupportedLanguage.Alingual
    ];

    protected override DateOnly? GetEstimatedReleaseDate(string expectedDate)
    {
        if (expectedDate.Contains("Release Date: TBC", StringComparison.OrdinalIgnoreCase))
            return null;

        Match match = EstimatedDateRegex().Match(expectedDate);

        if (match.Success == false)
            return null;

        GroupCollection groups = match.Groups;

        int day = groups[1].Value.ToLowerInvariant() switch
        {
            "early" => 1,
            "middle" => 11,
            "late" => 21,
            _ => 1
        };

        string monthAbbreviation = groups[2].Value.Replace(".", "");
        int month = DateTime.ParseExact(monthAbbreviation, "MMM", CultureInfo.InvariantCulture).Month;

        int year = Convert.ToInt32(groups[3].Value);

        return new DateOnly(year, month, day);
    }

    protected override DateOnly? GetSalesDate(string salesDate)
    {
        Match match = SalesDateRegex().Match(salesDate);

        if (match.Success == false)
            return null;

        string monthAbbreviation = match.Groups[1].Value;
        int day = int.Parse(match.Groups[2].Value);
        int year = int.Parse(match.Groups[3].Value);

        int month = DateTime.ParseExact(monthAbbreviation, "MMM", CultureInfo.InvariantCulture).Month;

        return new(year, month, day);
    }
}