@page "/month"
@rendermode InteractiveWebAssembly
@attribute [Authorize]
@inject ITimetrackerService TrackerService
@inject IHolidayService HolidayService
@inject AuthenticationStateProvider AuthStateProvider

<PageTitle>@_deCulture.DateTimeFormat.GetMonthName(_month) @_year – Monatsübersicht – Timetracker</PageTitle>

@if (_loading)
{
    <MudStack AlignItems="AlignItems.Center" Class="mt-16" Spacing="3">
        <MudProgressCircular Color="Color.Primary" Indeterminate="true" Size="Size.Large" />
        <MudText Color="Color.Secondary">Lade Monatsdaten…</MudText>
    </MudStack>
}
else
{
    <MudStack Spacing="3">

        @* ── Monats-Header ── *@
        <MudPaper Elevation="4" Class="pa-5 rounded-xl"
                  Style="background: #1E293B; color: white;">
            <MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween">
                <MudIconButton Icon="@Icons.Material.Filled.ChevronLeft"
                               Style="color:white" Size="Size.Large" OnClick="PrevMonth" />
                <MudStack Spacing="0" AlignItems="AlignItems.Center">
                    <MudText Typo="Typo.h5" Style="color:white; font-weight:700; letter-spacing:0.5px">
                        @_deCulture.DateTimeFormat.GetMonthName(_month) @_year
                    </MudText>
                    <MudText Typo="Typo.caption" Style="color:rgba(255,255,255,0.72)">
                        @_subLabel
                    </MudText>
                </MudStack>
                <MudStack Row="true" AlignItems="AlignItems.Center" Spacing="0">
                    @if (!IsCurrentMonth)
                    {
                        <MudButton Variant="Variant.Text" Style="color:white"
                                   OnClick="GoToCurrentMonth" Size="Size.Small">
                            Heute
                        </MudButton>
                    }
                    <MudIconButton Icon="@Icons.Material.Filled.ChevronRight"
                                   Style="color:white" Size="Size.Large" OnClick="NextMonth" />
                </MudStack>
            </MudStack>
        </MudPaper>

        @* ── Monatstabelle ── *@
        <MudCard Elevation="3" Class="rounded-xl">
            <MudCardContent Class="pa-0">
                <MudSimpleTable Dense="true" Striped="false" Hover="true" Style="overflow-x:auto">
                    <thead>
                        <tr style="background: rgba(14,165,233,0.08);">
                            <th style="font-weight:700; padding:10px 16px">Tag</th>
                            <th style="font-weight:700; padding:10px 16px">Start</th>
                            <th style="font-weight:700; padding:10px 16px">Ende</th>
                            <th style="font-weight:700; padding:10px 16px">Netto</th>
                            <th style="font-weight:700; padding:10px 16px">Gleitzeit</th>
                            <th style="font-weight:700; padding:10px 16px">Status</th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach (var d in _days)
                        {
                            <tr style="@GetRowStyle(d)">
                                <td style="padding:8px 16px; white-space:nowrap">
                                    <MudStack Spacing="0">
                                        <MudText Typo="Typo.body2" Style="@($"font-weight:{(d.IsToday ? "700" : "500")}")">
                                            @d.Date.ToString("ddd, dd. MMM", _deCulture)
                                        </MudText>
                                    </MudStack>
                                </td>
                                <td style="padding:8px 16px">
                                    @(d.StartTime.HasValue ? d.StartTime.Value.ToString(@"HH\:mm") : "—")
                                </td>
                                <td style="padding:8px 16px">
                                    @(d.EndTime.HasValue ? d.EndTime.Value.ToString(@"HH\:mm") : "—")
                                </td>
                                <td style="padding:8px 16px">
                                    @(d.Net.HasValue ? FormatTs(d.Net.Value) : "—")
                                </td>
                                <td style="padding:8px 16px; color:@(d.Overtime >= TimeSpan.Zero ? "#4CAF50" : "#FF9800"); font-weight:600">
                                    @(d.Net.HasValue ? FormatTs(d.Overtime, sign: true) : "—")
                                </td>
                                <td style="padding:8px 16px">
                                    @GetStatusChip(d)
                                </td>
                            </tr>
                        }
                    </tbody>
                </MudSimpleTable>
            </MudCardContent>
        </MudCard>

        @* ── Monatszusammenfassung ── *@
        <MudPaper Elevation="4" Class="pa-5 rounded-xl"
                  Style="background: linear-gradient(135deg, rgba(14,165,233,0.08) 0%, rgba(14,165,233,0.02) 100%); border-left: 6px solid #0EA5E9;">
            <MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2" Class="mb-4">
                <MudIcon Icon="@Icons.Material.Filled.CalendarViewMonth" Color="Color.Primary" />
                <MudText Typo="Typo.h6" Style="font-weight:700">Monatszusammenfassung</MudText>
            </MudStack>
            <MudGrid Spacing="3">
                <MudItem xs="6" sm="4" md="2">
                    <MudStack Spacing="0" AlignItems="AlignItems.Center">
                        <MudText Typo="Typo.h5" Color="Color.Primary" Style="font-weight:700">
                            @FormatTs(_monthNet)
                        </MudText>
                        <MudText Typo="Typo.caption" Color="Color.Secondary">Netto gesamt</MudText>
                    </MudStack>
                </MudItem>
                <MudItem xs="6" sm="4" md="2">
                    <MudStack Spacing="0" AlignItems="AlignItems.Center">
                        <MudText Typo="Typo.h5"
                                 Style="@($"font-weight:700; color:{(_monthOvertime >= TimeSpan.Zero ? "#4CAF50" : "#FF9800")}")">
                            @FormatTs(_monthOvertime, sign: true)
                        </MudText>
                        <MudText Typo="Typo.caption" Color="Color.Secondary">Gleitzeit</MudText>
                    </MudStack>
                </MudItem>
                <MudItem xs="6" sm="4" md="2">
                    <MudStack Spacing="0" AlignItems="AlignItems.Center">
                        <MudText Typo="Typo.h5" Color="Color.Default" Style="font-weight:700">
                            @_recordedWorkDays / @_totalWorkDays
                        </MudText>
                        <MudText Typo="Typo.caption" Color="Color.Secondary">Arbeitstage</MudText>
                    </MudStack>
                </MudItem>
                <MudItem xs="6" sm="4" md="2">
                    <MudStack Spacing="0" AlignItems="AlignItems.Center">
                        <MudText Typo="Typo.h5" Color="Color.Secondary" Style="font-weight:700">
                            @_vacationCount
                        </MudText>
                        <MudText Typo="Typo.caption" Color="Color.Secondary">Urlaubstage</MudText>
                    </MudStack>
                </MudItem>
                <MudItem xs="6" sm="4" md="2">
                    <MudStack Spacing="0" AlignItems="AlignItems.Center">
                        <MudText Typo="Typo.h5" Color="Color.Tertiary" Style="font-weight:700">
                            @_holidayCount
                        </MudText>
                        <MudText Typo="Typo.caption" Color="Color.Secondary">Feiertage</MudText>
                    </MudStack>
                </MudItem>
            </MudGrid>
        </MudPaper>

    </MudStack>
}

@code {
    private static readonly System.Globalization.CultureInfo _deCulture = new("de-DE");

    private bool _loading = true;
    private int _userId;
    private int _year = DateTime.Today.Year;
    private int _month = DateTime.Today.Month;
    private List<MonthDayVm> _days = [];
    private AppSettings _settings = new();

    private string _subLabel = "";
    private TimeSpan _monthNet;
    private TimeSpan _monthOvertime;
    private int _recordedWorkDays;
    private int _totalWorkDays;
    private int _vacationCount;
    private int _holidayCount;

    private bool IsCurrentMonth => _year == DateTime.Today.Year && _month == DateTime.Today.Month;

    protected override async Task OnInitializedAsync()
    {
        var authState = await AuthStateProvider.GetAuthenticationStateAsync();
        var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier);
        if (claim == null) return;
        _userId = int.Parse(claim.Value);
        _settings = await TrackerService.GetSettingsAsync(_userId);
        await LoadMonth();
        _loading = false;
    }

    private async Task LoadMonth()
    {
        var workDaysTask = TrackerService.GetMonthAsync(_userId, _year, _month);
        var holidaysTask = HolidayService.GetHolidaysAsync(_year, _settings.GermanState);
        var vacationsTask = TrackerService.GetVacationDaysAsync(_userId, _year);

        await Task.WhenAll(workDaysTask, holidaysTask, vacationsTask);

        var workDays = await workDaysTask;
        var holidays = await holidaysTask;
        var vacations = await vacationsTask;

        var holidayMap = holidays.ToDictionary(h => h.Date, h => h.Name);
        var vacationSet = vacations.Select(v => v.Date).ToHashSet();

        var daysInMonth = DateTime.DaysInMonth(_year, _month);
        var today = DateOnly.FromDateTime(DateTime.Today);
        _days = Enumerable.Range(1, daysInMonth).Select(day =>
        {
            var date = new DateOnly(_year, _month, day);
            var wd = workDays.FirstOrDefault(w => w.Date == date);
            var isWorkDay = _settings.IsWorkDay(date.DayOfWeek);

            TimeSpan? net = null;
            if (wd?.StartTime != null && wd.EndTime != null)
            {
                var gross = wd.EndTime.Value.ToTimeSpan() - wd.StartTime.Value.ToTimeSpan();
                var breaks = wd.Breaks
                    .Where(b => b.StartTime.HasValue && b.EndTime.HasValue && b.EndTime > b.StartTime)
                    .Aggregate(TimeSpan.Zero, (s, b) =>
                        s + (b.EndTime!.Value.ToTimeSpan() - b.StartTime!.Value.ToTimeSpan()));
                var minMinutes = gross.TotalHours >= 9.0 ? 45 : 30;
                var minBreak = TimeSpan.FromMinutes(Math.Max(minMinutes, _settings.MinimumBreakMinutes));
                var finalBreak = breaks > minBreak ? breaks : minBreak;
                net = gross - finalBreak;
                if (net < TimeSpan.Zero) net = null;
            }

            var target = isWorkDay ? TimeSpan.FromHours(_settings.DailyTargetHours) : TimeSpan.Zero;
            var overtime = net.HasValue ? net.Value - target : TimeSpan.Zero;

            return new MonthDayVm
            {
                Date = date,
                StartTime = wd?.StartTime,
                EndTime = wd?.EndTime,
                Net = net,
                Overtime = overtime,
                HolidayName = holidayMap.GetValueOrDefault(date),
                IsVacation = vacationSet.Contains(date),
                IsWorkDay = isWorkDay,
                IsToday = date == today
            };
        }).ToList();

        // Summaries
        _monthNet = _days.Where(d => d.Net.HasValue).Aggregate(TimeSpan.Zero, (s, d) => s + d.Net!.Value);
        _monthOvertime = _days
            .Where(d => d.IsWorkDay && d.Net.HasValue)
            .Aggregate(TimeSpan.Zero, (s, d) => s + d.Overtime);
        _recordedWorkDays = _days.Count(d => d.IsWorkDay && d.Net.HasValue);
        _totalWorkDays = _days.Count(d => d.IsWorkDay && string.IsNullOrEmpty(d.HolidayName) && !d.IsVacation);
        _vacationCount = _days.Count(d => d.IsVacation);
        _holidayCount = _days.Count(d => !string.IsNullOrEmpty(d.HolidayName));

        var recorded = _recordedWorkDays;
        var total = _totalWorkDays;
        _subLabel = recorded == 0 ? "Noch keine Einträge diesen Monat" : $"{recorded} von {total} Arbeitstagen erfasst";
    }

    private async Task PrevMonth()
    {
        var d = new DateOnly(_year, _month, 1).AddMonths(-1);
        _year = d.Year; _month = d.Month;
        await LoadMonth();
    }

    private async Task NextMonth()
    {
        var d = new DateOnly(_year, _month, 1).AddMonths(1);
        _year = d.Year; _month = d.Month;
        await LoadMonth();
    }

    private async Task GoToCurrentMonth()
    {
        _year = DateTime.Today.Year; _month = DateTime.Today.Month;
        await LoadMonth();
    }

    private static string FormatTs(TimeSpan ts, bool sign = false)
    {
        var neg = ts < TimeSpan.Zero;
        var abs = neg ? ts.Negate() : ts;
        var h = (int)abs.TotalHours;
        var m = abs.Minutes;
        if (!sign) return $"{h}:{m:D2} h";
        return neg ? $"–{h}:{m:D2} h" : $"+{h}:{m:D2} h";
    }

    private string GetRowStyle(MonthDayVm d)
    {
        if (d.IsToday) return "background: rgba(63,81,181,0.10);";
        if (!string.IsNullOrEmpty(d.HolidayName)) return "background: rgba(0,150,136,0.07);";
        if (d.IsVacation) return "background: rgba(255,152,0,0.08);";
        if (!d.IsWorkDay) return "background: rgba(0,0,0,0.03); color: #90A4AE;";
        if (d.Net.HasValue) return "background: rgba(76,175,80,0.06);";
        return "";
    }

    private RenderFragment GetStatusChip(MonthDayVm d) => builder =>
    {
        void Chip(string text, string color)
        {
            builder.OpenElement(0, "span");
            builder.AddAttribute(1, "style",
                $"display:inline-block; padding:2px 10px; border-radius:12px; font-size:0.75rem; font-weight:600; background:{color}20; color:{color}; border:1px solid {color}60;");
            builder.AddContent(2, text);
            builder.CloseElement();
        }

        if (d.IsToday && !d.Net.HasValue && d.IsWorkDay) Chip("Heute", "#3F51B5");
        else if (!string.IsNullOrEmpty(d.HolidayName)) Chip(d.HolidayName, "#009688");
        else if (d.IsVacation) Chip("Urlaub", "#FF9800");
        else if (!d.IsWorkDay) Chip("Frei", "#90A4AE");
        else if (d.Net.HasValue) Chip("Erfasst", "#4CAF50");
        else Chip("Ausstehend", "#CFD8DC");
    };

    private sealed class MonthDayVm
    {
        public DateOnly Date { get; set; }
        public TimeOnly? StartTime { get; set; }
        public TimeOnly? EndTime { get; set; }
        public TimeSpan? Net { get; set; }
        public TimeSpan Overtime { get; set; }
        public string? HolidayName { get; set; }
        public bool IsVacation { get; set; }
        public bool IsWorkDay { get; set; }
        public bool IsToday { get; set; }
    }
}
