using BigRegister.Api.Data;
using BigRegister.Domain.Diplomas;
using BigRegister.Domain.Documents;
using BigRegister.Domain.People;
using BigRegister.Domain.Registrations;

namespace BigRegister.Api.Contracts;

/// <summary>Domain → wire DTO mapping (the anti-corruption boundary, server side).</summary>
public static class Mappers
{
    private static string D(DateOnly d) => d.ToString("yyyy-MM-dd");

    public static RegistrationStatusDto ToDto(this RegistrationStatus s) => new(
        Tag: s.Tag.ToString(),
        HerregistratieDatum: s.HerregistratieDatum is { } h ? D(h) : null,
        GeschorstTot: s.GeschorstTot is { } g ? D(g) : null,
        Reden: s.Reden,
        DoorgehaaldOp: s.DoorgehaaldOp is { } x ? D(x) : null);

    public static RegistrationDto ToDto(this Registration r) => new(
        r.BigNummer, r.Naam, r.Beroep, D(r.Registratiedatum), D(r.Geboortedatum), r.Status.ToDto());

    public static AdresDto ToDto(this Adres a) => new(a.Straat, a.Postcode, a.Woonplaats);

    public static PersonDto ToDto(this Person p) => new(p.Naam, D(p.Geboortedatum), p.Adres.ToDto());

    public static PolicyQuestionDto ToDto(this PolicyQuestion q) => new(
        q.Id, q.Vraag, q.Type == QuestionType.JaNee ? "ja-nee" : "tekst");

    public static DuoDiplomaDto ToDto(this Diploma d) => new(
        d.Id, d.Naam, d.Instelling, d.Jaar,
        DiplomaRules.ProfessionFor(d),
        DiplomaRules.QuestionsFor(d).Select(q => q.ToDto()).ToList());

    public static DocumentCategoryDto ToDto(this DocumentCategory c) => new(
        c.CategoryId, c.Label, c.Description, c.Required, c.AcceptedTypes, c.MaxSizeMb, c.Multiple, c.AllowPostDelivery);

    // Aanvraag status is COMPUTED ON READ: an auto-approvable submission reports
    // Goedgekeurd once past the processing window, else In behandeling; a manual case
    // stays In behandeling forever (awaits the unbuilt backoffice). Pure — testable
    // by passing different `now` values without waiting for the wall clock.
    public static AanvraagStatusDto ToStatusDto(this Aanvraag a, DateTimeOffset now)
    {
        if (!a.Submitted)
            return new("Concept", StepIndex: a.StepIndex, StepCount: a.StepCount);
        if (a.Reden is not null)
            return new("Afgewezen", Referentie: a.Referentie, Reden: a.Reden);
        if (a.AutoApprovable && now > a.SubmittedAt!.Value + ApplicationStore.ProcessingWindow)
            return new("Goedgekeurd", Referentie: a.Referentie);
        return new("InBehandeling", Referentie: a.Referentie, Manual: !a.AutoApprovable);
    }

    public static ApplicationSummaryDto ToSummaryDto(this Aanvraag a, DateTimeOffset now) => new(
        a.Id, a.Type, a.ToStatusDto(now), a.DocumentIds,
        a.CreatedAt.ToString("o"), a.UpdatedAt.ToString("o"), a.SubmittedAt?.ToString("o"));

    public static ApplicationDetailDto ToDetailDto(this Aanvraag a, DateTimeOffset now) => new(
        a.Id, a.Type, a.ToStatusDto(now), a.Draft, a.DocumentIds,
        a.CreatedAt.ToString("o"), a.UpdatedAt.ToString("o"), a.SubmittedAt?.ToString("o"));
}
