#nullable enable
using Baya.Domain.Entities.Catalog;
using Baya.Domain.Entities.User;
using Baya.Domain.Entities.Verification;
using Baya.Infrastructure.Persistence.Configuration.GeographyConfig;

namespace Baya.Infrastructure.Persistence.Services.Seeding;

/// <summary>
/// The static, deterministic description of the Development demo marketplace the <see cref="DemoWorldSeeder"/>
/// materialises. Kept as plain data (not inline in the seeder) so the exact demo world — the phone numbers a
/// developer logs in with, which nurse is verified, the priced variants and coverage — reads at a glance and
/// stays the single source of truth for the runbook / frontend de-mock hand-off.
/// <para>
/// All money is <b>IRR Rials as an integer</b> (no Toman, no float). Category ids are the fixed catalog seed
/// ids (<c>1…5</c>); the Tehran city id and district ids are the fixed geography seed ids.
/// </para>
/// </summary>
internal static class DemoWorldDefinitions
{
    public const long TehranCityId = GeographySeed.TehranCityId;

    // Tehran municipal district ids from the geography seed (1000 + n).
    public const long District1 = 1001;
    public const long District2 = 1002;
    public const long District3 = 1003;
    public const long District6 = 1006;
    public const long District12 = 1012;

    // Catalog category ids from the catalog seed.
    public const long ElderlyCare = 1;
    public const long PostSurgery = 2;
    public const long InfantCare = 3;
    public const long ChronicIllness = 4;

    /// <summary>The single cross-category, required demo pricing dimension (شیفت / shift type). Seeding it in
    /// Development gives the frontend variant builder a required option-group to render on the real path
    /// (the "fresh catalog has categories but no option groups" data gap) without polluting a production DB.</summary>
    public const string ShiftGroupNameEn = "Shift Type";
    public const string ShiftGroupNameFa = "نوع شیفت";

    public const string ShiftDaytime = "Daytime";
    public const string ShiftNight = "Night";
    public const string ShiftLiveIn = "Live-in";

    public static readonly (string NameFa, string NameEn)[] ShiftValues =
    [
        ("روزانه", ShiftDaytime),
        ("شبانه", ShiftNight),
        ("شبانه‌روزی", ShiftLiveIn),
    ];

    public static readonly NursePersona[] Nurses =
    [
        new NursePersona(
            Phone: "09120000001",
            UserName: "demo_nurse_azizi",
            Name: "زهرا",
            FamilyName: "عزیزی",
            Gender: "female",
            NationalId: "0012345678",
            Bio: "پرستار سالمند با هشت سال سابقه مراقبت در منزل.",
            YearsOfExperience: 8,
            IsVerified: true,
            Credentials:
            [
                new CredentialDef(CredentialTypes.MohCompetencyLicense, "پروانه صلاحیت وزارت بهداشت", "MOH-84512"),
                new CredentialDef(CredentialTypes.CriminalRecord, "گواهی عدم سوء پیشینه", "CR-2025-1187"),
            ],
            Bank: new BankDef("بانک ملت", "زهرا عزیزی", "IR820170000000123456789012", MatchedNationalId: true),
            Variants:
            [
                new VariantDef(ElderlyCare, PriceUnits.Per24H, 3_500_000, SessionCount: null, ShiftLiveIn, "مراقبت شبانه‌روزی سالمند"),
                new VariantDef(ElderlyCare, PriceUnits.PerHour, 250_000, SessionCount: null, ShiftDaytime, "مراقبت ساعتی سالمند"),
                new VariantDef(PostSurgery, PriceUnits.PerDay, 2_000_000, SessionCount: null, ShiftDaytime, "مراقبت روزانه پس از جراحی"),
            ],
            Areas:
            [
                new AreaDef(TehranCityId, null),        // whole-city Tehran
                new AreaDef(TehranCityId, District1),
                new AreaDef(TehranCityId, District3),
            ]),

        new NursePersona(
            Phone: "09120000002",
            UserName: "demo_nurse_karimi",
            Name: "علی",
            FamilyName: "کریمی",
            Gender: "male",
            NationalId: "0023456789",
            Bio: "پرستار مراقبت پس از جراحی و بیماری‌های مزمن.",
            YearsOfExperience: 5,
            IsVerified: true,
            Credentials:
            [
                new CredentialDef(CredentialTypes.MohCompetencyLicense, "پروانه صلاحیت وزارت بهداشت", "MOH-77120"),
            ],
            Bank: new BankDef("بانک ملی", "علی کریمی", "IR330120000000098765432101", MatchedNationalId: true),
            Variants:
            [
                new VariantDef(ChronicIllness, PriceUnits.PerDay, 1_800_000, SessionCount: null, ShiftDaytime, "مدیریت روزانه بیماری مزمن"),
                new VariantDef(PostSurgery, PriceUnits.Per24H, 3_200_000, SessionCount: null, ShiftLiveIn, "مراقبت شبانه‌روزی پس از جراحی"),
            ],
            Areas:
            [
                new AreaDef(TehranCityId, District3),
                new AreaDef(TehranCityId, District6),
                new AreaDef(TehranCityId, District12),
            ]),

        // Unverified: has a profile + a variant + a covered area, but is_verified=0 so the search-index
        // maintainer computes is_searchable=0 and this nurse must never surface in discovery.
        new NursePersona(
            Phone: "09120000003",
            UserName: "demo_nurse_ahmadi",
            Name: "مریم",
            FamilyName: "احمدی",
            Gender: "female",
            NationalId: null,
            Bio: "در انتظار تکمیل مراحل احراز هویت.",
            YearsOfExperience: 2,
            IsVerified: false,
            Credentials: [],
            Bank: null,
            Variants:
            [
                new VariantDef(InfantCare, PriceUnits.PerSession, 800_000, SessionCount: 1, ShiftDaytime, "مراقبت جلسه‌ای نوزاد"),
            ],
            Areas:
            [
                new AreaDef(TehranCityId, District2),
            ]),
    ];

    /// <summary>
    /// Demo backoffice operators so the admin console is reachable through the same phone-OTP login the
    /// customers/nurses use (admin sub-roles are server-granted, never self-selectable via <c>select_role</c>,
    /// so they must be seeded). Two roles are seeded on purpose: a <c>super_admin</c> that sees every console
    /// (including RBAC) and a scoped <c>finance</c> operator, so the frontend's <c>useAdminCapabilities()</c>
    /// role-gating is demonstrable — the finance operator's sidebar shows only the money consoles.
    /// </summary>
    public static readonly AdminPersona[] Admins =
    [
        new AdminPersona("09120000020", "demo_admin_root", "نگار", "مدیری", "female", RoleNames.SuperAdmin),
        new AdminPersona("09120000021", "demo_admin_finance", "کامران", "مالی", "male", RoleNames.Finance),
    ];

    public static readonly CustomerPersona[] Customers =
    [
        new CustomerPersona(
            Phone: "09120000010",
            UserName: "demo_customer_mohammadi",
            Name: "سارا",
            FamilyName: "محمدی",
            Gender: "female",
            EmergencyContactName: "بهرام محمدی",
            EmergencyContactPhone: "09121110010",
            Patients:
            [
                new PatientDef("حسن محمدی", "حسن", "محمدی", "male", new DateOnly(1948, 3, 15), "A+", "سابقه فشار خون و دیابت."),
                new PatientDef("فاطمه محمدی", "فاطمه", "محمدی", "female", new DateOnly(1955, 9, 2), "O+", "بدون سابقه بیماری خاص."),
            ],
            Addresses:
            [
                new AddressDef("خانه", District3, "تهران، ونک، خیابان ملاصدرا، پلاک ۱۲", "1991834511", "بهرام محمدی", "09121110010", 35.7595m, 51.4100m, IsPrimary: true),
            ]),

        new CustomerPersona(
            Phone: "09120000011",
            UserName: "demo_customer_hosseini",
            Name: "رضا",
            FamilyName: "حسینی",
            Gender: "male",
            EmergencyContactName: "نازنین حسینی",
            EmergencyContactPhone: "09121110011",
            Patients:
            [
                new PatientDef("امیرعلی حسینی", "امیرعلی", "حسینی", "male", new DateOnly(2025, 1, 20), "B+", "نوزاد سالم، نیازمند مراقبت روزانه."),
            ],
            Addresses:
            [
                new AddressDef("خانه", District6, "تهران، سعادت‌آباد، بلوار دریا، پلاک ۴۵", "1998765432", "نازنین حسینی", "09121110011", 35.7870m, 51.3760m, IsPrimary: true),
            ]),
    ];
}

internal sealed record NursePersona(
    string Phone,
    string UserName,
    string Name,
    string FamilyName,
    string Gender,
    string? NationalId,
    string Bio,
    int YearsOfExperience,
    bool IsVerified,
    CredentialDef[] Credentials,
    BankDef? Bank,
    VariantDef[] Variants,
    AreaDef[] Areas);

internal sealed record AdminPersona(
    string Phone,
    string UserName,
    string Name,
    string FamilyName,
    string Gender,
    string RoleName);

internal sealed record CredentialDef(string Type, string IssuingAuthority, string Number);

internal sealed record BankDef(string BankName, string AccountHolderName, string Iban, bool MatchedNationalId);

internal sealed record VariantDef(
    long CategoryId,
    string PriceUnit,
    long Price,
    int? SessionCount,
    string ShiftValueEn,
    string DisplayName);

internal sealed record AreaDef(long CityId, long? DistrictId);

internal sealed record CustomerPersona(
    string Phone,
    string UserName,
    string Name,
    string FamilyName,
    string Gender,
    string EmergencyContactName,
    string EmergencyContactPhone,
    PatientDef[] Patients,
    AddressDef[] Addresses);

internal sealed record PatientDef(
    string DisplayName,
    string FirstName,
    string LastName,
    string Gender,
    DateOnly BirthDate,
    string BloodType,
    string InitialMedicalNotes);

internal sealed record AddressDef(
    string Title,
    long DistrictId,
    string AddressLine,
    string PostalCode,
    string RecipientName,
    string RecipientPhone,
    decimal Latitude,
    decimal Longitude,
    bool IsPrimary);
