export interface User {
    uuid: string;
    id: number;
    mobile_number: string;
    name?: string | null;
    first_name?: string | null;
    last_name?: string | null;
    email: string | null;
    roles: string[];
    is_active: boolean;
    created_at: string;
    updated_at?: string;
}

export interface UserProfile {
    uuid: string;
    blood_group: string | null;
    weight: number | null;
    height: number | null;
    diseases: string | null;
    medications: string | null;
    allergies: string | null;
    insurance_type: string | null;
}

export interface Doctor {
    uuid: string;
    first_name: string;
    last_name: string;
    medical_code: string;
    gender: "male" | "female";
    degree: string;
    bio: string | null;
    profile_image: string | null;
    is_active: boolean;
    specialties: Specialty[];
    created_at: string;
}

export interface Clinic {
    uuid: string;
    name: string;
    phone: string | null;
    logo: string | null;
    is_active: boolean;
    doctors_count: number;
    created_at: number;
    owner_mobile: string | null;
}

export interface ClinicDetail {
    id: string;
    uuid: string;
    name: string | null;
    title: string | null;
    is_active: boolean;
    phone: string | null;
    phone_number: string | null;
    logo: string | null;
    clinic_logo: string | null;
    caption: string | null;
    images_clinic: { url: string; fid?: number }[];
    social_media: {
        instagram: string | null;
        telegram: string | null;
        aparat: string | null;
        youtube: string | null;
        linkedin: string | null;
    } | null;
    specialties: { id: string; uuid: string; name: string }[];
    services: { id: string; uuid: string; name: string }[];
    list_bime: { id: string; uuid: string; name: string }[];
    doctors: number;
    city: { id: string; name: string }[];
    state: { id: string; name: string }[];
    location: string | null;
    map: { latitude: string | null; longitude: string | null };
    "24_7": boolean;
    field_working_days: string | null;
}

export type AppointmentStatus =
    | "pending"
    | "confirmed"
    | "completed"
    | "cancelled_by_doctor"
    | "cancelled_by_user"
    | "no_show"
    | "expired"
    | "following_up"
    | "salon";

export interface Appointment {
    uuid: string;
    patient_name: string;
    patient_mobile: string;
    doctor_uuid: string;
    doctor_name: string;
    slot_start: number;
    slot_end: number;
    appointment_date: string;
    appointment_time: string;
    end_time: string;
    status: AppointmentStatus;
    version: number;
    created_at: string;
    patient_uuid?: string;
    patient_national_code?: string | null;
    patient_gender?: string | null;
    is_reserve?: boolean;
    deposit_required?: boolean;
    deposit_amount_rials?: number | null;
    note?: string | null;
    service_section?: { uuid: string; name: string } | null;
    service_item?: { uuid: string; name: string } | null;
    staff?: { uuid: string; full_name: string } | null;
    visit_price_rials?: number | null;
    service_items?: { uuid: string; name: string; price_rials?: number | null; service_category?: string | null; insurance_covered?: boolean }[] | null;
    /** نوع خدمتِ بیمه‌ای و بیمهٔ پایهٔ انتخاب‌شده روی همین نوبت. */
    insurance_service_category?: string | null;
    insurance_service_category_label?: string | null;
    insurance_base_id?: number | null;
    /** محلِ نوبت‌دهی این نوبت. null = مطب شخصی. مبنای تشخیص روش نوبت‌دهی. */
    clinic_uuid?: string | null;
    /** فقط در حالت نوبت‌دهی سرویسی پر می‌شوند؛ در حالت اسلاتی null. */
    service_total_minutes?: number | null;
    service_buffer_minutes?: number | null;
}

export interface AppointmentEvent {
    type: string;
    title: string;
    actor_name: string | null;
    reason: string | null;
    created_at: number;
}

export type DiscountRuleType =
    | 'patient_tag'
    | 'invoice_amount'
    | 'specific_patient'
    | 'occasion'
    | 'service'
    | 'visit_count';

export interface DiscountRule {
    uuid: string;
    name: string;
    type: DiscountRuleType;
    discount_type: 'percent' | 'fixed';
    value: number;
    priority: number;
    combinable: boolean;
    active: boolean;
    valid_from: number | null;
    valid_to: number | null;
    target_tag_uuid: string | null;
    target_record_uuid: string | null;
    target_service_item_uuid: string | null;
    min_amount_rials: number | null;
    min_visit_count: number | null;
    occasion_kind: string | null;
    created_at: number;
    updated_at: number;
}

export interface SessionAuditEntry {
    field: string;
    operation: 'create' | 'update' | 'delete';
    old_value: string | null;
    new_value: string | null;
    actor_name: string | null;
    note: string | null;
    created_at: number;
}

export interface DiscountSuggestion {
    rule_uuid: string;
    rule_name: string;
    type: DiscountRuleType;
    discount_type: 'percent' | 'fixed';
    value: number;
    discount_rials: number;
    combinable: boolean;
    priority: number;
}

export type PaymentStatus =
    | "pending"
    | "success"
    | "failed"
    | "canceled"
    | "refunded";
export type PaymentGateway = "mellat" | "sep";

export interface Payment {
    uuid: string;
    amount: number;
    status: PaymentStatus;
    gateway: PaymentGateway;
    ref_id: string | null;
    card_pan?: string | null;
    refunds?: { amount: number; ref: string; at: number }[];
    patient_mobile: string;
    appointment_uuid: string | null;
    paid_at: string | null;
    created_at: string;
    order_id?: string;
    patient_name?: string | null;
    type?: string;
}

export type SettlementStatus = "pending" | "approved" | "rejected";

/** `mixed` فقط در نمای تجمیعی بیمار معنا دارد: مطالبات آن بیمار وضعیت یکسان ندارند. */
export type ClaimStatus = "pending" | "submitted" | "approved" | "rejected" | "paid" | "mixed";

/**
 * وضعیت پرداخت صورتحساب — از مجموع پرداخت‌های مراجعه در برابر سهم بیمار مشتق
 * می‌شود (ستون `invoices.status` فقط چرخه‌ی حیات است). با `PaymentStatus` درگاه فرق دارد.
 */
export type InvoiceListStatus = "paid" | "partial" | "unsettled";

export interface ClaimPatientRow {
    patient_uuid: string;
    record_uuid: string;
    full_name: string | null;
    mobile: string | null;
    national_code: string | null;
    claims_count: number;
    total_services_rials: number;
    total_insurance_rials: number;
    total_patient_rials: number;
    total_approved_rials: number;
    total_paid_rials: number;
    overall_status: ClaimStatus;
    /** بیمه‌هایی که این بیمار زیرشان مطالبه دارد — واژگان مطالبه: base | supplementary. */
    insurances: ClaimInsuranceRef[];
    last_activity_at: number;
}

export interface ClaimInsuranceRef {
    insurance_id: number;
    insurance_name: string | null;
    kind: string | null;
}

export interface ClaimStatusLogEntry {
    uuid: string;
    from_status: string | null;
    to_status: string;
    note: string | null;
    by: string | null;
    at: number;
}

export interface ClaimDetailRow {
    uuid: string;
    invoice_uuid: string | null;
    visit_date: number | null;
    doctor_name: string | null;
    insurance_id: number;
    insurance_name: string | null;
    insurance_kind: "base" | "supplementary";
    service_base_rials: number;
    coverage_percent: number;
    insurance_share_rials: number;
    patient_share_rials: number;
    total_approved_rials: number | null;
    total_paid_rials: number | null;
    status: ClaimStatus;
    tracking_number: string | null;
    reject_reason: string | null;
    submitted_at: number | null;
    settled_at: number | null;
    created_at: number;
    allowed_transitions: string[];
    logs: ClaimStatusLogEntry[];
}

export interface Settlement {
    uuid: string;
    representation_name: string;
    amount: number;
    status: SettlementStatus;
    bank_card: string | null;
    bank_name: string | null;
    reject_reason: string | null;
    requested_at: string;
    processed_at: string | null;
}

export interface Representation {
    id: number;
    uuid: string;
    full_name: string;
    domain?: string | null;
    is_global?: boolean;
    mobile_number: string | null;
    city_id: number | null;
    city_ids?: number[];
    cities?: { id: number; name: string }[];
    city: string | null;
    commission_percent: number;
    bank_account: { card?: string; bank_name?: string; iban?: string } | null;
    wallet_balance?: number;
    doctor_count?: number;
    appointment_count?: number;
    active?: boolean;
    is_active?: boolean;
    created_at: string;
}

export interface Comment {
    uuid: string;
    patient_name: string;
    doctor_name: string;
    title: string;
    body: string;
    is_approved: boolean;
    created_at: string;
}

export interface Rating {
    uuid: string;
    patient_name: string;
    doctor_name: string;
    diagnosis_accuracy: number;
    skill: number;
    behavior: number;
    cleanliness: number;
    waiting_time: number;
    overall: number;
    created_at: string;
}

export type SmsTemplateStatus = "draft" | "pending" | "approved" | "rejected";

export interface SmsTemplate {
    uuid: string;
    name: string;
    body: string;
    provider_code: string | null;
    status: SmsTemplateStatus;
    admin_note: string | null;
    created_at: string;
}

export interface SmsLog {
    uuid: string;
    recipient: string;
    message: string;
    status: "queued" | "sent" | "failed";
    provider: string;
    tag: string;
    template: string | null;
    sent_at: string | null;
    created_at: string;
}

export interface AppLog {
    id: number;
    level: string;
    message: string;
    context: string | null;
    channel: string | null;
    path: string | null;
    created_at: number;
}

export interface SmsMessageText {
    tag: string;
    title: string;
    body: string;
    variables: string[];
    kavenegar_template: string | null;
    token_map: Record<string, string>;
    updated_at: number | null;
}

export interface Province {
    id: number;
    uuid: string;
    name: string;
    status: number;
    weight: number;
}

export interface City {
    id: number;
    uuid: string;
    name: string;
    site_name?: string | null;
    title?: string | null;
    status: number;
    weight: number;
    province_id: number | null;
    representation_id?: number | null;
    contact_phone?: string | null;
    email?: string | null;
    description?: string | null;
    slogan?: string | null;
    domain?: string | null;
    keywords?: string | null;
    footer_description?: string | null;
    social_media?: Record<string, string> | null;
    logo_url?: string | null;
}

export interface SpecialtyFull {
    id: number;
    uuid: string;
    name: string;
    slug: string;
    status: number;
    weight: number;
    parent_id: number | null;
}

export interface DoctorService {
    id: number;
    uuid: string;
    name: string;
    slug: string;
    status: number;
    weight: number;
    specialty_id: number | null;
}

export interface Insurance {
    id: number;
    uuid: string;
    name: string;
    type: "basic" | "supplementary";
    logo_url: string | null;
    status: number;
    /** درصد پوشش مرکزی به تفکیک نوع خدمت — `{ outpatient: 70, inpatient: 30 }`. */
    coverage_defaults?: Record<string, number>;
}

export interface Tag {
    id: number;
    uuid: string;
    name: string;
    slug: string;
    status: number;
}

export interface Blog {
    uuid: string;
    title: string;
    slug: string;
    summary: string | null;
    body: string;
    image_url: string | null;
    status: "draft" | "published";
    author?: { uuid: string; name: string } | null;
    /** null = مقاله سراسری (روی همه دامنه‌ها، canonical روی دامنه اصلی) */
    city?: { id: string; name: string } | null;
    tags: string[];
    /** منابع E-E-A-T مقاله‌های تولیدشده توسط پایپ‌لاین محتوا */
    sources?: { url: string; title: string }[];
    /** null = پست دستی ادمین، خارج از گیت بازبینی؛ در غیر این صورت وضعیت بازبینی پزشک */
    review_status?: "pending_review" | "approved" | "rejected" | null;
    reviewer?: { uuid: string; name: string } | null;
    reviewed_at?: number | null;
    review_note?: string | null;
    /** کلید یکتای موضوع پایپ‌لاین (specialty, angle) */
    topic_slug?: string | null;
    // SEO
    meta_title?: string | null;
    meta_description?: string | null;
    primary_keyword?: string | null;
    secondary_keywords?: string[];
    faq?: { q: string; a: string }[];
    internal_links?: (string | { url: string; anchor?: string })[];
    external_links?: (string | { url: string; anchor?: string })[];
    reading_time?: number | null;
    canonical_url?: string | null;
    og_image?: string | null;
    /** زمان انتشار خودکار (unix)، null = دستی */
    scheduled_at?: number | null;
    /** نمایندهٔ مالک، null = پست ادمین/سراسری */
    representation?: { uuid: string; name: string; domain?: string | null } | null;
    created_at: string;
    updated_at?: string;
}

export interface Secretary {
    uuid: string;
    secretary_uuid?: string;
    user_name: string;
    mobile_number: string;
    doctor_name: string;
    doctor_uuid: string;
    is_active: boolean;
    national_code?: string | null;
    address?: string | null;
    permissions: SecretaryPermissions;
    created_at: string;
    clinic_uuid?: string | null;
    clinic_name?: string | null;
    /** سهم منشی از نوبت‌های آنلاین — per-relation، توسط ادمین تنظیم می‌شود. */
    online_share_enabled?: boolean;
    online_share_percent?: number;
    earnings?: {
        total_rials: number;
        this_month_rials: number;
        appointments_count: number;
    };
}

export interface SecretaryPermissions {
    appointments: {
        view: boolean;
        create: boolean;
        cancel: boolean;
        update_status: boolean;
    };
    patients: {
        view: boolean;
        create: boolean;
        update: boolean;
        delete: boolean;
    };
    payments: {
        view: boolean;
        create: boolean;
        update: boolean;
        delete: boolean;
    };
    insurances: {
        view: boolean;
        create: boolean;
        update: boolean;
        delete: boolean;
    };
    addresses: {
        view: boolean;
        create: boolean;
        update: boolean;
        delete: boolean;
    };
    clinic_info: {
        view: boolean;
        update: boolean;
    };
    inventory: {
        view: boolean;
        create: boolean;
        update: boolean;
        delete: boolean;
    };
    tags: {
        view: boolean;
        create: boolean;
        update: boolean;
        delete: boolean;
    };
    services: {
        view: boolean;
        create: boolean;
        update: boolean;
        delete: boolean;
    };
    staff: {
        view: boolean;
        create: boolean;
        update: boolean;
        delete: boolean;
    };
    discounts: {
        view: boolean;
        create: boolean;
        update: boolean;
        delete: boolean;
    };
    sms: {
        view: boolean;
        create: boolean;
        update: boolean;
        delete: boolean;
    };
    appointment_settings: {
        view: boolean;
        update: boolean;
    };
    clinic_doctors: {
        view: boolean;
        create: boolean;
        update: boolean;
        delete: boolean;
    };
    subscription: {
        view: boolean;
        create: boolean;
    };
}

export interface Specialty {
    id?: number;
    uuid: string;
    name: string;
    slug?: string;
}

export interface ClinicStaff {
    uuid: string;
    full_name: string;
    phone: string | null;
    job_title: string | null;
    address: string | null;
    national_code: string | null;
    active: boolean;
    /** حساب ورود به پنل با نقش ROLE_STAFF */
    has_account: boolean;
    user_uuid: string | null;
    created_at: number;
}

/** یک قلم از سرویس‌های تخصیص‌یافته به پرسنل — خروجی GET /api/v1/dashboard/staff */
export interface StaffAssignedService {
    uuid: string;
    name: string;
    section_name: string;
    price_rials: number;
    duration_minutes: number | null;
}

export interface SubscriptionPlan {
    uuid: string;
    name: string;
    level: number;
    max_secretaries: number;
    features: Record<string, boolean>;
    active: boolean;
    periods: SubscriptionPeriod[];
}

export interface SubscriptionPeriod {
    uuid: string;
    label: string;
    duration_months: number;
    price_rials: number;
    is_trial: boolean;
}

export interface MySubscriptionData {
    subscription: {
        plan: {
            name: string;
            level: number;
            max_secretaries: number;
            features: Record<string, boolean>;
        };
        period?: { label: string; duration_months: number };
        is_trial: boolean;
        starts_at?: number;
        expires_at?: number | null;
        days_remaining?: number;
    } | null;
    used_trial: boolean;
    /** پلن مؤثر: پلن اشتراک فعال یا پلن پیش‌فرض free در نبود اشتراک. */
    effective_plan: {
        name: string;
        level: number;
        max_secretaries: number;
        features: Record<string, boolean>;
    } | null;
}
/** @deprecated use MySubscriptionData */
export interface MySubscription {
    plan: { name: string; level: number; features: Record<string, boolean> };
    period?: { label: string; duration_months: number };
    is_trial: boolean;
    starts_at?: number;
    expires_at?: number | null;
    used_trial: boolean;
    days_remaining?: number;
}

export interface ServiceSection {
    uuid: string;
    name: string;
    active: boolean;
    /** number of services in this section (only present in the list endpoint) */
    items_count?: number;
}

/** یک قلم کالای تکی روی سرویس (خروجی ServiceItemConsumable::toArray) */
export interface ServiceConsumable {
    item_uuid: string;
    name: string;
    unit: string;
    price: number;   // Rial
    stock: number;
    amount: number;
}

export interface ServiceItem {
    uuid: string;
    name: string;
    price_rials: number;
    section_uuid?: string;
    section_name?: string;
    /** پکیج کالای مصرفی متصل به این خدمت (اختیاری) */
    inventory_package_uuid?: string | null;
    inventory_package_title?: string | null;
    /** اقلام کالای تکی — مستقل از پکیج و قابل استفاده هم‌زمان با آن */
    consumables?: ServiceConsumable[];
    created_at?: number;
    updated_at?: number;
    /** primary staff (first member) — kept for backward compatibility */
    staff: { uuid: string; full_name: string } | null;
    /** all personnel assigned to this service */
    staff_members?: { uuid: string; full_name: string }[];
    active: boolean;
    insurance_covered?: boolean;
    /** نوع خدمت (سرپایی/بستری) — درصد پوشش بیمه بر همین اساس انتخاب می‌شود. */
    service_category?: string;
    service_category_label?: string;
    duration_minutes?: number | null;
    bookable?: boolean;
}

export interface SmsWalletBalance {
    balance_rials: number;
    sms_price_rials: number;
    estimated_sms_count: number;
}

export interface SmsWalletLog {
    uuid: string;
    type: "credit" | "debit";
    amount_rials: number;
    description: string;
    created_at: number;
}

export interface SmsSettings {
    reminder_enabled: boolean;
    reminder_hours_before: number;
    post_visit_enabled: boolean;
    post_visit_text: string | null;
    post_visit_text_pending?: string | null;
    post_visit_text_status?: "none" | "pending" | "approved" | "rejected";
    post_visit_text_reject_reason?: string | null;
}

export interface PatientProfile {
    full_name?: string | null;
    name?: string | null;
    family?: string | null;
    fathers_name?: string | null;
    national_code?: string | null;
    gender?: string | null;
    date_of_birth?: number | null;
    blood_type?: string | null;
    marital_status?: string | null;
    education?: string | null;
    field_of_study?: string | null;
    job?: string | null;
    address?: string | null;
    province_id?: number | null;
    city_id?: number | null;
    postal_code?: string | null;
    referral_source?: string | null;
    description?: string | null;
    home_phone?: string | null;
    work_phone?: string | null;
    mobile?: string | null;
    basic_insurance_id?: number | null;
    basic_insurance_name?: string | null;
    supplementary_insurance_id?: number | null;
    supplementary_insurance_name?: string | null;
}

/** بدنه‌ی PATCH /api/v1/patient/{uuid} — تمام کلیدها اختیاری (partial update). */
export interface PatientProfileUpdate {
    name?: string;
    mobile?: string;
    national_code?: string;
    gender?: string | null;
    fathers_name?: string | null;
    date_of_birth?: number | null;
    marital_status?: string | null;
    education?: string | null;
    field_of_study?: string | null;
    job?: string | null;
    basic_insurance_id?: number | null;
    supplementary_insurance_id?: number | null;
    province_id?: number | null;
    city_id?: number | null;
    home_phone?: string | null;
    address?: string | null;
    postal_code?: string | null;
    referral_source?: string | null;
    description?: string | null;
}

export interface PatientRecord {
    uuid: string;
    entity_type: string;
    entity_id: number;
    user_uuid?: string;
    user_name?: string | null;
    user_mobile?: string | null;
    user_national_code?: string | null;
    /** clinic case-file number */
    record_number?: string | null;
    /** record labels (TenantTag) */
    tags?: { uuid: string; name: string; color: string }[];
    created_at: number;
    profile?: PatientProfile | null;
}

export interface SessionServiceLine {
    uuid: string;
    service_item_uuid: string;
    service_name: string;
    staff_uuid: string | null;
    staff_name: string | null;
    price_rials: number;
    quantity: number;
    line_total_rials: number;
    created_at: number;
}

export interface PatientAppointment {
    uuid: string;
    starts_at: number;
    ends_at: number | null;
    status: string;
    doctor_name: string | null;
    service_name: string | null;
    price_rials: number | null;
    created_at: number;
}

export interface PatientSession {
    uuid: string;
    record_uuid: string;
    appointment_uuid: string | null;
    doctor_uuid?: string | null;
    doctor_name?: string | null;
    insurance_base_id: number | null;
    insurance_supplementary_id: number | null;
    visit_price_rials: number;
    base_insurance_discount_percent: string;
    supplementary_discount_percent: string;
    services_total_rials: number;
    /** تفکیک بیمه — سرور محاسبه می‌کند؛ کلاینت هرگز خودش نسازد */
    gross_total_rials?: number;
    base_insurance_rials?: number;
    supplementary_insurance_rials?: number;
    patient_share_rials?: number;
    final_price_rials: number;
    remaining_rials?: number;
    paid_total_rials?: number;
    payment_method: string;
    is_paid?: boolean;
    services?: SessionServiceLine[];
    invoice_uuid?: string | null;
    invoice_status?: string | null;
    patient_debt_rials?: number;
    notes: string | null;
    created_at: number;
    updated_at: number;
}

// ── شعبه، ساعت کاری و اتاق ───────────────────────────────────────────────────
// «شعبه» جدول تازه‌ای نیست: همان رکورد آدرس محل نوبت‌دهی است (`doctor_addresses`)،
// همان چیزی که `WeeklySchedule.sessions[].location_id` به آن اشاره می‌کند. پس
// Branch شکلِ `DoctorAddress::toArray()` است به‌علاوهٔ دو شمارشِ فهرست.

export interface Branch {
    id: string;
    uuid: string;
    type: 'personal' | 'clinic';
    clinic_id: number | null;
    clinic_name: string | null;
    name: string | null;
    map: { latitude: string | null; longitude: string | null };
    address: string | null;
    telephone: string | null;
    active: boolean;
    timezone: string;
    city: { id: string; name: string } | null;
    province: { id: string; name: string } | null;
    /** فقط در `GET /api/v1/branches` — شعبهٔ بدون ساعت «تعریف‌نشده» است، نه همیشه‌باز */
    working_hours_defined?: boolean;
    /** فقط در `GET /api/v1/branches` — تعداد اتاق‌های فعال */
    rooms_count?: number;
}

/** دقیقه از نیمه‌شب، نه رشتهٔ `"09:00"` — مقایسه و تقاطع باید عددی بماند. */
export interface WorkingHourRange {
    sequence: number;
    start_minute: number;
    end_minute: number;
    start_time: string;
    end_time: string;
    active: boolean;
}

export interface BranchWorkingHours {
    branch_uuid: string;
    timezone: string;
    defined: boolean;
    /** کلیدهای `"0"`..`"6"`؛ ۰ = شنبه، همان قرارداد محاسبهٔ اسلات */
    days: Record<string, WorkingHourRange[]>;
}

/**
 * بدنهٔ نوشتن ساعت کاری. عمداً شکل خواندن (`WorkingHourRange`) نیست: `sequence` را
 * سرور از ترتیب بازه‌ها مشتق می‌کند و `start_time`/`end_time` فقط برای نمایش‌اند.
 */
export type WorkingHoursPayload = Record<string, { start_minute: number; end_minute: number }[]>;

export interface Room {
    uuid: string;
    address_uuid: string;
    address_name: string | null;
    name: string;
    room_type: string | null;
    /** ظرفیت هم‌زمان: اتاق سه‌تخته یک اتاق با ظرفیت ۳ است، نه سه اتاق */
    capacity: number;
    floor: string | null;
    active: boolean;
    created_at: number;
    updated_at: number;
}

export interface RoomPayload {
    name: string;
    room_type?: string | null;
    capacity?: number;
    floor?: string | null;
    active?: boolean;
}

// ── منابع: نوع، منبع، مهارت، استخر ───────────────────────────────────────────
// «تقویم مال منبع است، نه مال پزشک» — منبع هر چیزی است که ممکن است اشغال باشد.
// هر منبع مال یک شعبه است، و شعبه همان آدرس محل نوبت‌دهی است.

export interface ResourceType {
    uuid: string;
    code: string;
    name: string;
    /** نوع‌های doctor/staff/room را backfill می‌سازد و حذف نمی‌شوند */
    is_system: boolean;
    active: boolean;
    resources_count?: number;
    created_at: number;
    updated_at: number;
}

export interface Skill {
    uuid: string;
    name: string;
    active: boolean;
    resources_count?: number;
    created_at: number;
    updated_at: number;
}

export interface ResourceSkillLine {
    skill_uuid: string;
    skill_name: string;
    /** ۱..۵ — تسک بعدی استراتژی «حفظ متخصص‌ها» را روی همین می‌سازد */
    level: number;
}

export interface ClinicResource {
    uuid: string;
    name: string;
    address_uuid: string;
    address_name: string | null;
    type_uuid: string;
    type_code: string;
    type_name: string;
    /** ظرفیت هم‌زمان: اتاق سه‌تخته یک منبع با ظرفیت ۳ است، نه سه منبع */
    capacity: number;
    /** جزو نوبت بیمار نیست، ولی منبع را اشغال می‌کند */
    setup_minutes: number;
    cleanup_minutes: number;
    attributes: Record<string, string | number | boolean>;
    /** `null` یعنی دستگاه/تجهیزات — منبعی که پل به موجودیت دیگری ندارد */
    subject_kind: 'doctor' | 'staff' | 'room' | null;
    subject_uuid: string | null;
    skills: ResourceSkillLine[];
    active: boolean;
    created_at: number;
    updated_at: number;
}

export interface ResourcePayload {
    name: string;
    address_uuid?: string;
    type_uuid?: string;
    capacity?: number;
    setup_minutes?: number;
    cleanup_minutes?: number;
    attributes?: Record<string, string | number | boolean>;
    active?: boolean;
}

export interface ResourcePoolMemberLine {
    resource_uuid: string;
    resource_name: string;
    priority: number;
    active: boolean;
}

export interface ResourcePool {
    uuid: string;
    name: string;
    address_uuid: string;
    address_name: string | null;
    type_uuid: string;
    type_code: string;
    type_name: string;
    members: ResourcePoolMemberLine[];
    active: boolean;
    created_at: number;
    updated_at: number;
}

// ── تقویم منبع، استثنا و تعطیلات ─────────────────────────────────────────────

export interface ResourceCalendarDays {
    resource_uuid: string;
    timezone: string;
    defined: boolean;
    /** کلیدهای `"0"`..`"6"`؛ ۰ = شنبه */
    days: Record<string, WorkingHourRange[]>;
}

export type ResourceExceptionType = 'leave' | 'absence' | 'maintenance' | 'closure';

export interface ResourceException {
    uuid: string;
    resource_uuid: string;
    resource_name: string;
    type: ResourceExceptionType;
    type_label: string;
    /** timestamp مطلق — استثنا می‌تواند چندروزه باشد */
    starts_at: number;
    ends_at: number;
    reason: string | null;
    created_at: number;
    updated_at: number;
}

export interface AvailabilityInterval {
    start: number;
    end: number;
}

export interface AvailabilityDay {
    date: number;
    day_of_week: number;
    intervals: AvailabilityInterval[];
    total_minutes: number;
    /** چرا روز خالی است — بدون این، پاسخ خالی از باگ قابل تشخیص نیست */
    reasons: string[];
}

export interface ResourceAvailability {
    resource_uuid: string;
    timezone: string;
    days: AvailabilityDay[];
}

export interface NationalHoliday {
    uuid: string;
    date: number;
    jalali_date: string;
    jalali_year: number;
    title: string;
    /** `null` یعنی این محیط استثنایی ندارد */
    overridden_working?: boolean | null;
}

export interface HolidayOverride {
    uuid: string;
    date: number;
    is_working: boolean;
    note: string | null;
    created_at: number;
}

// ── قوانین (تسک ۰۹/۱۰) ────────────────────────────────────────────────────────

export type PolicyCategory =
    | 'selection'
    | 'eligibility'
    | 'resource'
    | 'timing'
    | 'spacing'
    | 'pricing';

export interface PolicyClause {
    field: string;
    operator: string;
    value: unknown;
}

export interface PolicyCondition {
    match?: 'all' | 'any';
    conditions?: PolicyClause[];
}

export interface PolicyEffect {
    type: string;
    value?: unknown;
    reason?: string;
}

export interface Policy {
    uuid: string;
    category: PolicyCategory;
    name: string;
    condition: PolicyCondition;
    effects: PolicyEffect[];
    priority: number;
    version: number;
    active: boolean;
    valid_from: number | null;
    valid_to: number | null;
    address_uuid: string | null;
    service_uuid: string | null;
    catalog_category_uuid: string | null;
    specificity: number;
    versions?: PolicyVersionLog[];
}

export interface PolicyVersionLog {
    version: number;
    snapshot: Record<string, unknown>;
    created_at: number;
}

export interface PolicyFieldMeta {
    key: string;
    label: string;
    type: 'int' | 'uuid' | 'enum' | 'bool' | 'list';
    /** فقط عملگرهایی که برای این نوع معنا دارند — فرم باید همین را نشان دهد */
    operators: string[];
    values?: string[];
}

export interface PolicyEffectMeta {
    type: string;
    label: string;
    value_type: 'none' | 'int' | 'string';
    combination: string;
}

export interface PolicyCategorySchema {
    label: string;
    fields: string[];
    operators: string[];
    field_meta: PolicyFieldMeta[];
    effects: PolicyEffectMeta[];
}

export type PolicySchema = Record<PolicyCategory, PolicyCategorySchema>;

export interface PolicyTemplateInput {
    key: string;
    type: string;
    label: string;
    min?: number;
    max?: number;
}

export interface PolicyTemplate {
    key: string;
    title: string;
    description: string;
    category: PolicyCategory;
    inputs: PolicyTemplateInput[];
}

export interface SimulationRow {
    appointment_uuid: string;
    patient_name: string;
    slot_start: number;
    before: string;
    after: string;
    reason: string;
}

export interface PolicySimulationRun {
    uuid: string;
    policy_uuid: string;
    policy_version: number;
    sample_size: number;
    affected_count: number;
    affected_percent: number;
    severity: 'none' | 'low' | 'medium' | 'high';
    created_at: number;
    rows: SimulationRow[];
    warning: string | null;
}

// ── پکیج و اعتبار جلسات (تسک ۱۱) ─────────────────────────────────────────────

export interface PackageDefinition {
    uuid: string;
    name: string;
    session_count: number;
    price_rials: number;
    /** `null` یعنی بی‌پایان */
    validity_days: number | null;
    active: boolean;
    services: { uuid: string; name: string }[];
    created_at: number;
}

export interface PatientPackage {
    uuid: string;
    package_uuid: string;
    package_name: string;
    patient_uuid: string;
    session_count: number;
    price_paid_rials: number;
    purchased_at: number;
    valid_to: number | null;
    expired: boolean;
    /** همیشه از جمع دفتر می‌آید — هیچ ستونی در دیتابیس نیست */
    balance: number;
}

export interface CreditLedgerRow {
    uuid: string;
    kind: 'purchase' | 'consume' | 'refund' | 'adjustment' | 'expiry';
    delta: number;
    appointment_uuid: string | null;
    service_uuid: string | null;
    service_name: string | null;
    reason: string | null;
    created_by: string | null;
    created_at: number;
    /** در UI محاسبه‌شده نیست — سرور همان جمع تجمعی را می‌دهد */
    running_balance: number;
}

export interface CreditLedger {
    package: PatientPackage;
    rows: CreditLedgerRow[];
}

// ── دورهٔ درمان (تسک ۱۲) ──────────────────────────────────────────────────────

export interface CourseProtocolStep {
    session_number: number;
    params: Record<string, string | number | boolean>;
    override_duration_minutes: number | null;
}

export interface CourseProtocol {
    uuid: string;
    service_uuid: string;
    service_name: string;
    session_count: number;
    min_days: number;
    ideal_days: number;
    max_days: number;
    prefer_same_resource: boolean;
    active: boolean;
    steps: CourseProtocolStep[];
    created_at: number;
}

export interface CourseSessionRow {
    uuid: string;
    session_number: number;
    params: Record<string, string | number | boolean>;
    appointment_uuid: string | null;
    slot_start: number | null;
    status: 'planned' | 'booked' | 'completed' | 'skipped';
    completed_at: number | null;
}

export interface CourseProgress {
    completed: number;
    booked: number;
    planned: number;
    skipped: number;
    total: number;
    next_session_number: number | null;
    next_params: Record<string, string | number | boolean>;
    last_completed_at: number | null;
}

export interface TreatmentCourse {
    uuid: string;
    patient_uuid: string;
    service_uuid: string;
    service_name: string;
    protocol_uuid: string;
    session_count: number;
    min_days: number;
    ideal_days: number;
    max_days: number;
    patient_package_uuid: string | null;
    preferred_resource_uuid: string | null;
    preferred_resource_name: string | null;
    package_balance?: number | null;
    package_shortfall?: number | null;
    status: 'active' | 'completed' | 'abandoned';
    abandon_reason: string | null;
    started_at: number;
    completed_at: number | null;
    progress: CourseProgress;
    sessions?: CourseSessionRow[];
}

export interface NextSlotSuggestion {
    session_number: number | null;
    params: Record<string, string | number | boolean>;
    ideal_at?: number;
    range?: { min: number; max: number };
    suggested_slots: { start: number; end: number }[];
    warning: string | null;
}

// ── لغو و لیست انتظار (تسک ۱۳) ───────────────────────────────────────────────

export interface CancellationPolicy {
    uuid: string;
    service_uuid: string | null;
    service_name: string | null;
    free_window_hours: number;
    penalty_mode: 'none' | 'percent' | 'fixed';
    penalty_value: number;
    deposit_refundable: boolean;
    credit_refundable: boolean;
    no_show_threshold: number;
    risk_tag_uuid: string | null;
    active: boolean;
    created_at: number;
}

export interface CancellationPreview {
    penalty_rials: number;
    deposit_refundable: boolean;
    credit_refundable: boolean;
    within_free_window: boolean;
    notes: string[];
    paid_rials: number;
}

export interface CancellationResult extends Omit<CancellationPreview, 'paid_rials'> {
    appointment_uuid: string;
    status: string;
    released_resources: number;
    waitlist_notified: number;
    penalty_charged: boolean;
}

export interface WaitlistEntry {
    uuid: string;
    patient_uuid: string;
    service_uuid: string;
    service_name: string;
    branch_id: number | null;
    desired_from: number;
    desired_to: number;
    preferred_day_parts: string[];
    priority: number;
    status: 'waiting' | 'notified' | 'converted' | 'expired';
    notified_at: number | null;
    notify_count: number;
    created_at: number;
}

// ── گزارش‌ها (تسک ۱۴) ────────────────────────────────────────────────────────

export interface UtilizationRow {
    resource_uuid: string;
    resource_name: string;
    role: string;
    available_minutes: number;
    occupied_minutes: number;
    active_minutes: number;
    /** `null` یعنی تقویمی نیست — تعریف‌نشده، نه صفر */
    utilization: number | null;
    active_ratio: number | null;
    wasted_capacity: boolean;
}

export interface AccuracyRow {
    service_uuid: string;
    service_name: string;
    sample_size: number;
    planned_minutes: number;
    actual_minutes: number;
    deviation_percent: number;
    /** `null` یعنی نمونه به آستانه نرسیده — شدتی ادعا نمی‌شود */
    severity: 'none' | 'low' | 'medium' | 'high' | null;
    below_min_sample: boolean;
}

export interface ReportEnvelope<T> {
    from: number;
    to: number;
    rows: T[];
}
