using GerbilManagerWebAPI.Models;

namespace GerbilManagerWebAPI.Import.Rpro3
{
    /// <summary>
    /// Quelle eines RPRO3-Tier-Datensatzes. „stamm" = eigenes Tier, „fremd" = externer Ahn,
    /// „wurftier" = Welpe eines Wurfs (nur relevant, wenn nicht in ein stamm-Tier überführt).
    /// </summary>
    public enum Rpro3Src { Stamm, Fremd, Wurftier }

    /// <summary>Einheitlicher Tier-Datensatz aus der RPRO3-SQLite (vor Dedup).
    /// `Rid` ist die RPRO3-ID im jeweiligen Namensraum: "N"=stamm, "uN"=fremd, "XjY"=wurftier.</summary>
    public sealed class Rpro3Animal
    {
        public required string Rid { get; init; }
        public Rpro3Src Src { get; init; }
        public string? Name { get; set; }
        public Gender Gender { get; set; }
        public DateOnly? Dob { get; set; }
        public string? Farbe { get; set; }      // _FARBE Farbschlagname
        public string? Fcode { get; set; }       // _FCODE 8-Locus-Genotyp
        public string? Origin { get; set; }      // aufgelöster Herkunfts-Name (herk_tb)
        public int? OriginHerkId { get; set; }   // herk_tb.id (1 = eigene Zucht)
        public string? Zb { get; set; }
        public string? MidRaw { get; set; }      // Mutter-Ref im RPRO3-Namensraum
        public string? PidRaw { get; set; }      // Vater-Ref im RPRO3-Namensraum
        public DateOnly? DateOfDeath { get; set; }
        public string? CauseOfDeath { get; set; }
        public string? Defects { get; set; }     // _FEHLER
        public bool IsCastrated { get; set; }
        public int? StatusCode { get; set; }     // stamm._STATUS (RPRO3)

        // Dedup-Schlüssel (normalisiert), wird von Rpro3Dedup gesetzt.
        public string NameKey { get; set; } = "";
        public string FarbeKey { get; set; } = "";
        public string OriginKey { get; set; } = "";
    }

    public sealed class Rpro3Litter
    {
        public required int Id { get; init; }
        public string? Name { get; set; }      // _BEZ "Wurf A"
        public DateOnly? Date { get; set; }    // _AM
        public string? MotherRid { get; set; } // stamm-id als string
        public string? FatherRid { get; set; }
        public string? Notes { get; set; }     // _BEM
    }

    public sealed class Rpro3Pup
    {
        public required string Id { get; init; }  // "XjY"
        public int WurfId { get; init; }
        public string? Name { get; set; }
        public Gender Gender { get; set; }
        public DateOnly? Dob { get; set; }
        public string? Sid { get; set; }          // → stamm-id, falls als eigenes Tier behalten
        public DateOnly? DateOfDeath { get; set; }
        public string? CauseOfDeath { get; set; }
        public DateOnly? AbgabeDate { get; set; }
        public int? AbnId { get; set; }           // → abn_tb
        public decimal? Price { get; set; }
        public string? Zb { get; set; }
        public string? Defects { get; set; }
    }

    public sealed class Rpro3Contact
    {
        public required int Id { get; init; }
        public required string Namespace { get; init; }  // "herk" | "abn"
        public string? Bez { get; set; }
        public string? Anrede { get; set; }
        public string? Vname { get; set; }
        public string? Nname { get; set; }
        public string? Clan { get; set; }
        public string? Str { get; set; }
        public string? Ort { get; set; }
        public string? Plz { get; set; }
        public string? Telp { get; set; }
        public string? Teld { get; set; }
        public string? Mail { get; set; }
        public string? Http { get; set; }
        public string? Memo { get; set; }
        public string? Bem { get; set; }

        /// <summary>Anzeigename: Bezeichnung/Cattery, sonst Clan, sonst Vor+Nachname.</summary>
        public string DisplayName =>
            FirstNonEmpty(Bez, Clan, $"{Vname} {Nname}".Trim()) ?? "Unbekannt";

        private static string? FirstNonEmpty(params string?[] vals) =>
            vals.FirstOrDefault(v => !string.IsNullOrWhiteSpace(v));
    }

    public sealed class Rpro3Weight
    {
        public required string Tid { get; init; } // stamm-id (waage) bzw. wurftier-id (jungwaage)
        public DateOnly? Date { get; set; }
        public int Grams { get; set; }
        public string? Notes { get; set; }
    }

    public sealed class Rpro3Health
    {
        public required string Tid { get; init; }
        public DateOnly? Date { get; set; }
        public string? Description { get; set; }
        public string? Medication { get; set; }
    }

    public sealed class Rpro3Diary
    {
        public required string Tid { get; init; }
        public DateOnly? Date { get; set; }
        public string? Title { get; set; }
        public string? Description { get; set; }
    }

    public sealed class Rpro3PhotoSet
    {
        public required string Tid { get; init; } // stamm-id
        public List<string> FileNames { get; } = new();
    }

    // ── Feature-Tabellen (becken/herktier/abgeben/abstat/getback/nachfrage/ausz) ──

    /// <summary>becken_tb: Gehege/Becken (id, _BEZ Name, _SIZE Maße, _MENGE Kapazität,
    /// _CLEANED letzte Reinigung JDN, _CYCLUS Reinigungsintervall Tage).</summary>
    public sealed class Rpro3Becken
    {
        public required int Id { get; init; }
        public string? Name { get; set; }
        public string? Size { get; set; }
        public int? Capacity { get; set; }
        public DateOnly? LastCleaned { get; set; }
        public int? CycleDays { get; set; }
    }

    /// <summary>herktier_tb: Erwerb eines Tieres (_TID stamm-id, _DATE Kaufdatum JDN,
    /// _PRICE Kaufpreis, _BEM Notiz).</summary>
    public sealed class Rpro3Acquisition
    {
        public required int Id { get; init; }
        public string? Tid { get; set; }          // stamm-id
        public DateOnly? Date { get; set; }
        public decimal? Price { get; set; }
        public string? Note { get; set; }
    }

    /// <summary>abgeben_tb: Reservierung/Vormerkung (tid stamm- oder wurftier-id, _RES reserviert?,
    /// _TERMIN Abgabetermin JDN, _ABN Abnehmer-Kontakt, _BEM Notiz).</summary>
    public sealed class Rpro3Abgeben
    {
        public required string Tid { get; init; } // stamm-id ("N") oder wurftier-id ("XjY")
        public bool Reserved { get; set; }
        public DateOnly? Appointment { get; set; }
        public int? AbnId { get; set; }
        public string? Note { get; set; }
    }

    /// <summary>abstat_tb: Abgabe-Abschluss (tid stamm-id, _IDABN Abnehmer-Kontakt,
    /// _AM Abgabedatum JDN, _PRICE Abgabepreis, _BEM Notiz).</summary>
    public sealed class Rpro3Abstat
    {
        public required string Tid { get; init; } // stamm-id
        public int? AbnId { get; set; }
        public DateOnly? HandedOver { get; set; }
        public decimal? Price { get; set; }
        public string? Note { get; set; }
    }

    /// <summary>getback_tb: Rücknahme (_TID stamm-/wurftier-id, _ZAM Rücknahmedatum JDN,
    /// _ZPREIS Rücknahmepreis, _AM ursprüngliches Abgabedatum JDN, _PREIS ursprünglicher Preis,
    /// _ABN Kontakt, von dem zurückkam, _BEM Notiz).</summary>
    public sealed class Rpro3Getback
    {
        public required int Id { get; init; }
        public string? Tid { get; set; }          // stamm- oder wurftier-id
        public DateOnly? ReturnDate { get; set; }
        public decimal? ReturnPrice { get; set; }
        public DateOnly? OriginalSaleDate { get; set; }
        public decimal? OriginalPrice { get; set; }
        public int? AbnId { get; set; }
        public string? Note { get; set; }
    }

    /// <summary>nachfrage_tb: Warteliste/Nachfrage (_COLOR Wunschfarbe, _SEX Wunschgeschlecht,
    /// _ABN Interessenten-Kontakt, _VOM Anfragedatum JDN, _STATUS Status, _BEM/_CODE Notiz).</summary>
    public sealed class Rpro3Nachfrage
    {
        public required int Id { get; init; }
        public string? WishColor { get; set; }
        public Gender WishGender { get; set; }
        public int? AbnId { get; set; }
        public DateOnly? RequestedAt { get; set; }
        public string? Status { get; set; }
        public string? Note { get; set; }
    }

    /// <summary>ausz_tb: Ausstellungsergebnis (_TID stamm-/wurftier-id, _VERANSTALTUNG Veranstaltung,
    /// _DATE Datum JDN, _ORT Ort, _PLATZ Platzierung, _AUSZ Auszeichnung, _JUROR/_EXTRA/_BEM Notiz).</summary>
    public sealed class Rpro3Ausstellung
    {
        public required int Id { get; init; }
        public string? Tid { get; set; }
        public string? EventName { get; set; }
        public DateOnly? Date { get; set; }
        public string? Place { get; set; }     // _ORT
        public string? Placement { get; set; } // _PLATZ
        public string? Award { get; set; }     // _AUSZ
        public string? Juror { get; set; }
        public string? Note { get; set; }
    }

    /// <summary>Vollständig geparster RPRO3-Backup-Inhalt.</summary>
    public sealed class Rpro3Data
    {
        public List<Rpro3Animal> Animals { get; } = new();          // stamm + fremd
        public Dictionary<int, Rpro3Litter> Litters { get; } = new();
        public Dictionary<string, Rpro3Pup> Pups { get; } = new();
        public Dictionary<string, Rpro3Contact> HerkContacts { get; } = new();
        public Dictionary<string, Rpro3Contact> AbnContacts { get; } = new();
        public List<Rpro3Weight> Weights { get; } = new();
        public List<Rpro3Health> Health { get; } = new();
        public List<Rpro3Diary> Diary { get; } = new();
        public Dictionary<string, Rpro3PhotoSet> Photos { get; } = new();

        // Feature-Tabellen.
        public List<Rpro3Becken> Becken { get; } = new();
        public List<Rpro3Acquisition> Acquisitions { get; } = new();
        public List<Rpro3Abgeben> Abgeben { get; } = new();
        public List<Rpro3Abstat> Abstat { get; } = new();
        public List<Rpro3Getback> Getback { get; } = new();
        public List<Rpro3Nachfrage> Nachfrage { get; } = new();
        public List<Rpro3Ausstellung> Ausstellungen { get; } = new();

        /// <summary>stamm-id (string) → becken_tb.id (Gehege-Zuordnung aus stamm_tb._BECKEN).
        /// Nur positive, gültige Becken-IDs.</summary>
        public Dictionary<string, int> StammBecken { get; } = new();

        // Roh-Zählungen (vor Dedup) für den Report.
        public int ColorStammCount { get; set; }
        public int ColorExtCount { get; set; }

        /// <summary>Löst eine RPRO3-Ref ("N"/"uN"/"XjY") in einen Anzeigenamen auf (für Provenance/Report).</summary>
        public Func<string?, string?> ResolveName { get; set; } = _ => null;
    }
}
