/**
 * Helpers purs de l'ecran « Modification client » (M1 Commercial, 1.12).
 *
 * Deux responsabilites, toutes deux testables unitairement (cf. clientEdit.spec.ts) :
 *  1. Pre-remplissage : mapper le payload `GET /api/clients/{id}` (embed
 *     contacts/adresses/ribs + scalaires) vers les brouillons « plats » edites
 *     par la page et les blocs reutilisables (mappers contacts/adresses/ribs/
 *     comptabilite reutilises depuis clientConsultation).
 *  2. Scoping STRICT des payloads PATCH (mode strict RG-1.28 / ERP-74) : chaque
 *     onglet n'envoie QUE les champs de SON groupe de serialisation, jamais un
 *     payload mixte — un champ hors-permission = 403 sur l'integralite cote back.
 *
 * Ces helpers ne touchent ni a l'API ni a l'etat reactif.
 *
 * NOTE RG-1.04 (Information obligatoire pour la Commerciale) : volontairement NON
 * miroitee cote front (cf. clientFormRules.ts) — /api/me n'expose pas le code de
 * role et Bureau partage les permissions de Commerciale. Le back l'applique de
 * maniere fiable (422) ; on laisse remonter ce 422 en toast.
 */

import {
    iriOf,
    relationOf,
    type ClientDetail,
} from '~/modules/commercial/utils/clientConsultation'
import type { AddressFormDraft, ContactFormDraft, RibFormDraft } from '~/modules/commercial/types/clientForm'

/**
 * Etat « plat » du bloc principal (groupe client:write:main). Distinct des
 * brouillons Contact : ces champs vivent sur le Client lui-meme (companyName,
 * categories, relation, triage), pas sur une sous-ressource ClientContact. Les
 * coordonnees de contact (nom, prenom, telephones, email) ne sont plus portees
 * par le Client : elles vivent exclusivement dans l'onglet Contacts.
 */
export interface MainFormDraft {
    companyName: string | null
    /** IRI des categories rattachees (M2M). */
    categoryIris: string[]
    relationType: 'distributeur' | 'courtier' | null
    distributorIri: string | null
    brokerIri: string | null
    triageService: boolean
}

/** Etat « plat » de l'onglet Information (groupe client:write:information). */
export interface InformationFormDraft {
    description: string | null
    competitors: string | null
    /** Date de creation de l'entreprise au format YYYY-MM-DD (MalioDate). */
    foundedAt: string | null
    /** Nombre de salaries en chaine (saisie masquee), converti en number au PATCH. */
    employeesCount: string | null
    revenueAmount: string | null
    profitAmount: string | null
    directorName: string | null
}

/** Etat « plat » de l'onglet Comptabilite (groupe client:write:accounting). */
export interface AccountingFormDraft {
    siren: string | null
    accountNumber: string | null
    nTva: string | null
    tvaModeIri: string | null
    paymentDelayIri: string | null
    paymentTypeIri: string | null
    bankIri: string | null
}

/** Permissions de l'utilisateur courant pertinentes pour l'edition d'un client. */
export interface ClientEditAbilities {
    /** `commercial.clients.manage` : bloc principal + onglets metier. */
    canManage: boolean
    /** `commercial.clients.accounting.view` : visibilite de l'onglet Comptabilite. */
    canAccountingView: boolean
    /** `commercial.clients.accounting.manage` : edition de l'onglet Comptabilite. */
    canAccountingManage: boolean
}

/** Editabilite resolue par zone d'onglet (deduite des permissions). */
export interface TabEditability {
    /** Bloc principal + onglets Information / Contact / Adresse editables. */
    businessEditable: boolean
    /** Onglet Comptabilite present (affiche). */
    accountingVisible: boolean
    /** Onglet Comptabilite editable. */
    accountingEditable: boolean
}

// ── Pre-remplissage (GET detail -> brouillons) ──────────────────────────────

/**
 * Mappe le detail client vers le brouillon du bloc principal. La relation
 * Distributeur/Courtier est resolue par exclusivite (RG-1.03) et son IRI extrait
 * de l'embed.
 */
export function mapMainDraft(client: ClientDetail): MainFormDraft {
    const relation = relationOf(client)

    return {
        companyName: client.companyName ?? null,
        categoryIris: (client.categories ?? []).map(c => c['@id']),
        relationType: relation.type,
        distributorIri: iriOf(client.distributor),
        brokerIri: iriOf(client.broker),
        triageService: client.triageService === true,
    }
}

/** Mappe le detail client vers le brouillon de l'onglet Information. */
export function mapInformationDraft(client: ClientDetail): InformationFormDraft {
    return {
        description: client.description ?? null,
        competitors: client.competitors ?? null,
        // MalioDate attend strictement YYYY-MM-DD : on tronque l'ISO datetime.
        foundedAt: client.foundedAt ? client.foundedAt.slice(0, 10) : null,
        employeesCount: client.employeesCount != null ? String(client.employeesCount) : null,
        revenueAmount: client.revenueAmount ?? null,
        profitAmount: client.profitAmount ?? null,
        directorName: client.directorName ?? null,
    }
}

/** Mappe les champs comptables du detail vers le brouillon de l'onglet (scalaires + IRI). */
export function mapAccountingFormDraft(client: ClientDetail): AccountingFormDraft {
    return {
        siren: client.siren ?? null,
        accountNumber: client.accountNumber ?? null,
        nTva: client.nTva ?? null,
        tvaModeIri: iriOf(client.tvaMode),
        paymentDelayIri: iriOf(client.paymentDelay),
        paymentTypeIri: iriOf(client.paymentType),
        bankIri: iriOf(client.bank),
    }
}

// ── Scoping strict des payloads PATCH ────────────────────────────────────────

/**
 * Payload du bloc principal — groupe client:write:main UNIQUEMENT. La relation
 * Distributeur/Courtier est mutuellement exclusive (RG-1.03) : on ne renseigne
 * que la FK correspondant au type choisi, l'autre est forcee a null.
 */
export function buildMainPayload(main: MainFormDraft): Record<string, unknown> {
    return {
        companyName: main.companyName,
        categories: main.categoryIris,
        distributor: main.relationType === 'distributeur' ? main.distributorIri : null,
        broker: main.relationType === 'courtier' ? main.brokerIri : null,
        triageService: main.triageService,
    }
}

/** Payload de l'onglet Information — groupe client:write:information UNIQUEMENT. */
export function buildInformationPayload(information: InformationFormDraft): Record<string, unknown> {
    return {
        description: information.description || null,
        competitors: information.competitors || null,
        foundedAt: information.foundedAt || null,
        employeesCount: information.employeesCount ? Number(information.employeesCount) : null,
        revenueAmount: information.revenueAmount || null,
        profitAmount: information.profitAmount || null,
        directorName: information.directorName || null,
    }
}

/**
 * Payload des scalaires de l'onglet Comptabilite — groupe client:write:accounting
 * UNIQUEMENT (les RIB passent par la sous-ressource /clients/{id}/ribs). La banque
 * n'a de sens que pour un Virement (RG-1.12) : forcee a null sinon.
 */
export function buildAccountingPayload(
    accounting: AccountingFormDraft,
    isBankRequired: boolean,
): Record<string, unknown> {
    return {
        siren: accounting.siren || null,
        accountNumber: accounting.accountNumber || null,
        tvaMode: accounting.tvaModeIri,
        nTva: accounting.nTva || null,
        paymentDelay: accounting.paymentDelayIri,
        paymentType: accounting.paymentTypeIri,
        bank: isBankRequired ? accounting.bankIri : null,
    }
}

/** Payload d'un contact (sous-ressource client_contact). */
export function buildContactPayload(contact: ContactFormDraft): Record<string, unknown> {
    return {
        firstName: contact.firstName || null,
        lastName: contact.lastName || null,
        jobTitle: contact.jobTitle || null,
        phonePrimary: contact.phonePrimary || null,
        phoneSecondary: contact.hasSecondaryPhone ? (contact.phoneSecondary || null) : null,
        email: contact.email || null,
    }
}

/** Payload d'une adresse (sous-ressource client_address). */
export function buildAddressPayload(
    address: AddressFormDraft,
    isBillingEmailRequired: boolean,
): Record<string, unknown> {
    return {
        isProspect: address.isProspect,
        isDelivery: address.isDelivery,
        isBilling: address.isBilling,
        country: address.country,
        postalCode: address.postalCode || null,
        city: address.city || null,
        street: address.street || null,
        streetComplement: address.streetComplement || null,
        categories: address.categoryIris,
        sites: address.siteIris,
        contacts: address.contactIris,
        billingEmail: isBillingEmailRequired ? (address.billingEmail || null) : null,
    }
}

/** Payload d'un RIB (sous-ressource client_rib). */
export function buildRibPayload(rib: RibFormDraft): Record<string, unknown> {
    return {
        label: rib.label,
        bic: rib.bic,
        iban: rib.iban,
    }
}

// ── Gating par permission ────────────────────────────────────────────────────

/**
 * Resout l'editabilite par zone a partir des permissions (option 1 ERP-74,
 * miroir UI du re-gating champ-par-champ du ClientProcessor) :
 *  - bloc principal + Information/Contact/Adresse : editables ssi `manage` ;
 *  - Comptabilite : visible ssi `accounting.view`, editable ssi `accounting.manage`.
 *
 * Produit le comportement attendu :
 *  - Admin : tout editable.
 *  - Bureau / Commerciale (manage, sans accounting) : metier editable, Compta masquee.
 *  - Compta (accounting seul, sans manage) : metier readonly, Compta editable.
 */
export function resolveTabEditability(abilities: ClientEditAbilities): TabEditability {
    return {
        businessEditable: abilities.canManage,
        accountingVisible: abilities.canAccountingView,
        accountingEditable: abilities.canAccountingManage,
    }
}
