@page "/calendar-event"
@page "/calendar-event/{DateStr}"
@page "/calendar-event/{DateStr}/{EventId}"
@attribute [Authorize]
@rendermode InteractiveServer

@inject IWorkDayService WorkDayService
@inject NavigationManager Navigation
@inject IJSRuntime JS

<PageTitle>Calendar Event</PageTitle>

<h1>Calendar Event</h1>

@if (!loaded)
{
    <p><em>Loading...</em></p>
}
else
{
    <div class="row g-3">
        <div class="col-12 col-md-6 col-lg-4">
            <label class="form-label">Start Date</label>
            <LocalizedDateInput InputId="calendar-event-date" TestId="calendar-event-start-date" Value="@selectedDate" ValueChanged="OnDateChangedAsync" />
        </div>

        <div class="col-12 col-md-6 col-lg-4">
            <label class="form-label">End Date</label>
            <LocalizedDateInput InputId="calendar-event-end-date" TestId="calendar-event-end-date" Value="@endDate" ValueChanged="OnEndDateChangedAsync" AllowEmpty="true" />
            <div class="form-text">Optional. Leave empty for a single-day event.</div>
        </div>

        <div class="col-12 col-md-6 col-lg-4">
            <label class="form-label">Entry Type</label>
            <select class="form-select" @bind="eventType">
                @foreach (var item in Enum.GetValues<CalendarEventType>())
                {
                    <option value="@item">@CalendarEventFormatter.GetEventTypeName(item)</option>
                }
            </select>
        </div>

        <div class="col-12 col-lg-8">
            <label class="form-label">Title</label>
            <input class="form-control" @bind="description" maxlength="120" placeholder="Optional" />
        </div>

        <div class="col-12 col-md-6 col-lg-4">
            <label class="form-label">Start Time</label>
            <input type="time" lang="it-IT" class="form-control" value="@startTimeStr" @onchange="OnStartTimeChanged" />
        </div>

        <div class="col-12 col-md-6 col-lg-4">
            <label class="form-label">End Time</label>
            <input type="time" lang="it-IT" class="form-control" value="@endTimeStr" @onchange="OnEndTimeChanged" />
        </div>

        <div class="col-12 col-md-6 col-lg-4">
            <label class="form-label text-muted">Duration</label>
            <div class="form-control-plaintext fw-bold">@FormatDuration()</div>
        </div>
    </div>

    <div class="d-flex align-items-center gap-2 mt-4">
        <button class="btn btn-primary" @onclick="SaveAsync">Save</button>
        @if (isExistingEvent)
        {
            <button class="btn btn-outline-danger" @onclick="DeleteAsync">Delete</button>
        }
        <button class="btn btn-outline-secondary" @onclick="BackToCalendar">Back to Calendar</button>
        @if (!string.IsNullOrWhiteSpace(statusMessage))
        {
            <span class="text-success">@statusMessage</span>
        }
    </div>
}

@code {
    [Parameter] public string? DateStr { get; set; }
    [Parameter] public string? EventId { get; set; }

    private bool loaded;
    private bool isExistingEvent;
    private DateOnly selectedDate = DateOnly.FromDateTime(DateTime.Today);
    private string eventId = string.Empty;
    private CalendarEventType eventType = CalendarEventType.Generic;
    private string description = string.Empty;
    private string? startTimeStr;
    private string? endTimeStr;
    private DateOnly? endDate;
    private string? statusMessage;

    protected override async Task OnInitializedAsync()
    {
        if (!string.IsNullOrEmpty(DateStr) && DateOnly.TryParseExact(DateStr, "yyyy-MM-dd", out var parsed))
        {
            selectedDate = parsed;
        }

        await LoadEventAsync();
        loaded = true;
    }

    private async Task LoadEventAsync()
    {
        if (string.IsNullOrWhiteSpace(EventId))
        {
            SetDefaults();
            return;
        }

        var existing = await WorkDayService.GetCalendarEventAsync(selectedDate, EventId);
        if (existing is not null)
        {
            eventId = existing.Id;
            selectedDate = existing.StartDate == default ? selectedDate : existing.StartDate;
            eventType = existing.EventType;
            description = existing.Description;
            startTimeStr = existing.StartTime?.ToString("HH:mm");
            endTimeStr = existing.EndTime?.ToString("HH:mm");
            endDate = existing.EndDate;
            isExistingEvent = true;
        }
        else
        {
            SetDefaults();
            statusMessage = "The selected calendar event was not found. A new event will be created for this day.";
        }
    }

    private void SetDefaults()
    {
        eventId = string.Empty;
        eventType = CalendarEventType.Generic;
        description = string.Empty;
        startTimeStr = null;
        endTimeStr = null;
        endDate = null;
        isExistingEvent = false;
    }

    private Task OnDateChangedAsync(DateOnly? value)
    {
        if (value.HasValue)
        {
            selectedDate = value.Value;
            statusMessage = null;
        }

        return Task.CompletedTask;
    }

    private Task OnEndDateChangedAsync(DateOnly? value)
    {
        endDate = value;
        statusMessage = null;
        return Task.CompletedTask;
    }

    private Task OnStartTimeChanged(ChangeEventArgs e)
    {
        startTimeStr = e.Value?.ToString();
        statusMessage = null;
        return Task.CompletedTask;
    }

    private Task OnEndTimeChanged(ChangeEventArgs e)
    {
        endTimeStr = e.Value?.ToString();
        statusMessage = null;
        return Task.CompletedTask;
    }

    private async Task SaveAsync()
    {
        var calendarEvent = new CalendarEventDocument
        {
            Id = eventId,
            StartDate = selectedDate,
            EndDate = endDate,
            EventType = eventType,
            Description = description,
            StartTime = ParseTime(startTimeStr),
            EndTime = ParseTime(endTimeStr)
        };

        var saved = await WorkDayService.SaveCalendarEventAsync(selectedDate, calendarEvent);
        eventId = saved.Id;
        isExistingEvent = true;
        startTimeStr = saved.StartTime?.ToString("HH:mm");
        endTimeStr = saved.EndTime?.ToString("HH:mm");
        Navigation.NavigateTo($"/calendar/{selectedDate:yyyy-MM}");
    }

    private async Task DeleteAsync()
    {
        if (!isExistingEvent || string.IsNullOrWhiteSpace(eventId))
        {
            return;
        }

        var eventName = CalendarEventFormatter.GetDisplayDescription(eventType, description);
        var confirmed = await JS.InvokeAsync<bool>("confirm", $"Delete calendar event '{eventName}' starting on {FormatDisplayDate(selectedDate)}?\nThis cannot be undone.");
        if (!confirmed)
        {
            return;
        }

        var deleted = await WorkDayService.DeleteCalendarEventAsync(selectedDate, eventId);
        if (deleted)
        {
            Navigation.NavigateTo($"/calendar/{selectedDate:yyyy-MM}");
            return;
        }

        statusMessage = "Unable to delete the calendar event.";
    }

    private void BackToCalendar()
    {
        Navigation.NavigateTo($"/calendar/{selectedDate:yyyy-MM}");
    }

    private decimal? GetDuration()
    {
        var start = ParseTime(startTimeStr);
        var end = ParseTime(endTimeStr);
        if (!start.HasValue || !end.HasValue || end <= start)
        {
            return null;
        }

        return Math.Round((decimal)(end.Value - start.Value).TotalHours, 2, MidpointRounding.AwayFromZero);
    }

    private string FormatDuration() => GetDuration() is { } duration ? FormatDurationHours(duration) : "—";

    private static string FormatDurationHours(decimal value)
    {
        var totalMinutes = (int)Math.Round(value * 60m, MidpointRounding.AwayFromZero);
        var hours = totalMinutes / 60;
        var minutes = totalMinutes % 60;
        return $"{hours:00}:{minutes:00}";
    }

    private static TimeOnly? ParseTime(string? value)
    {
        return !string.IsNullOrWhiteSpace(value) && TimeOnly.TryParse(value, out var parsed)
            ? parsed
            : null;
    }

    private static string FormatDisplayDate(DateOnly date)
    {
        return date.ToString("dddd dd/MM/yyyy");
    }
}