using Microsoft.EntityFrameworkCore;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using timetracker.Shared;

namespace timetracker.Data;

public class HolidayService(IDbContextFactory<TimetrackerDbContext> factory, HttpClient http) : IHolidayService
{
    private const string ApiUrl = "https://date.nager.at/api/v3/PublicHolidays/{0}/DE";

    public async Task<List<PublicHoliday>> GetHolidaysAsync(int year, string? stateCode = null)
    {
        await using var db = await factory.CreateDbContextAsync();
        var holidays = await db.PublicHolidays
            .Where(h => h.Date.Year == year)
            .OrderBy(h => h.Date)
            .ToListAsync();

        if (string.IsNullOrEmpty(stateCode))
        {
            // Default: return only global holidays (where Counties is null or empty)
            return holidays.Where(h => string.IsNullOrEmpty(h.Counties)).ToList();
        }

        // Return global holidays OR holidays that match the user's state code
        return holidays.Where(h => string.IsNullOrEmpty(h.Counties) || h.Counties.Split(',').Contains(stateCode)).ToList();
    }

    public async Task<(bool Success, string Message)> FetchAndStoreAsync(int year)
    {
        try
        {
            var url = string.Format(ApiUrl, year);
            var items = await http.GetFromJsonAsync<List<NagerHoliday>>(url);
            if (items == null) return (false, "Keine Daten erhalten.");

            await using var db = await factory.CreateDbContextAsync();
            var existing = await db.PublicHolidays.Where(h => h.Date.Year == year).ToListAsync();
            db.PublicHolidays.RemoveRange(existing);

            db.PublicHolidays.AddRange(items
                .Where(h => DateOnly.TryParse(h.Date, out _))
                .Select(h => new PublicHoliday
                {
                    Date = DateOnly.Parse(h.Date),
                    Name = h.LocalName,
                    Counties = h.Counties != null && h.Counties.Count > 0 ? string.Join(",", h.Counties) : null
                }));

            await db.SaveChangesAsync();
            return (true, $"{items.Count} Feiertage für {year} erfolgreich gespeichert.");
        }
        catch (Exception ex)
        {
            return (false, $"Fehler beim Abrufen: {ex.Message}");
        }
    }

    public async Task DeleteAsync(int id)
    {
        await using var db = await factory.CreateDbContextAsync();
        var h = await db.PublicHolidays.FindAsync(id);
        if (h != null)
        {
            db.PublicHolidays.Remove(h);
            await db.SaveChangesAsync();
        }
    }

    private sealed class NagerHoliday
    {
        [JsonPropertyName("date")]
        public string Date { get; set; } = "";

        [JsonPropertyName("localName")]
        public string LocalName { get; set; } = "";

        [JsonPropertyName("counties")]
        public List<string>? Counties { get; set; }
    }
}

