using TeleWave.Domain.Programming;

namespace TeleWave.Application.Programming.Templates.Generate;

/// <summary>Профиль в списке выбора: имя, на что похоже и для какой библиотеки годится.</summary>
public sealed record GridProfileDto(
    GridProfileKind Kind,
    string Name,
    string Reference,
    string Description
);

/// <summary>Строка предпросмотра — будущий слот так, как его покажут админу.</summary>
/// <param name="Block">Человеческое описание блока: «4 подряд», «до конца слота».</param>
public sealed record GridPlanSlotDto(
    GridPlanLayer Layer,
    int? Weekday,
    string Start,
    int DurationMinutes,
    string Title,
    Daypart Daypart,
    SlotKind SlotKind,
    string? GroupName,
    string Block
);

/// <summary>
/// План генерации целиком. <see cref="SlotsToRemove"/> больше нуля только в режиме пересборки —
/// это то, что будет снесено, и показать это до нажатия обязательно.
/// </summary>
public sealed record GridPlanDto(
    GridProfileKind Profile,
    string ProfileName,
    IReadOnlyList<GridPlanSlotDto> Slots,
    IReadOnlyList<PlanNote> Notes,
    int SlotsToRemove,
    string? FallbackGroupName,
    int FreeMinutes,
    int CoveredMinutes
);

public sealed record GenerateGridResultDto(int Created, int Removed);

/// <summary>Перевод плана в то, что уезжает на клиент. Общий для предпросмотра и результата.</summary>
public static class GridPlanMapper
{
    public static GridPlanDto ToDto(this GridPlan plan) =>
        new(
            plan.Profile.Kind,
            plan.Profile.Name,
            [.. plan.Slots.Select(ToDto)],
            plan.Notes,
            plan.SlotsToRemove,
            plan.FallbackGroupName,
            plan.FreeMinutes,
            plan.CoveredMinutes
        );

    private static GridPlanSlotDto ToDto(PlannedSlot slot) =>
        new(
            slot.Layer,
            slot.Weekday,
            $"{slot.Start.Hour:00}:{slot.Start.Minute:00}",
            slot.DurationMinutes,
            slot.Title,
            slot.Daypart,
            slot.SlotKind,
            slot.GroupName,
            Block(slot)
        );

    private static string Block(PlannedSlot slot) =>
        slot.SlotKind switch
        {
            SlotKind.SignOff => "конец вещания",
            SlotKind.Repeat => "повтор",
            _ => slot.BlockMode switch
            {
                SlotBlockMode.Count => $"{slot.BlockValue} подряд",
                SlotBlockMode.Duration => $"{slot.BlockValue} мин",
                _ => "до конца слота",
            },
        };
}
