/**
 * Helpers purs des écrans Consultation / Modification transporteur (M4, ERP-170) —
 * miroir de `providerDetail.ts` (M3). Mappent le payload `GET /api/carriers/{id}`
 * (relations embarquées via les groupes `carrier:item:read` + `qualimat:read` +
 * read-groups cross-module client/supplier/site/adresses) vers les brouillons
 * « plats » partagés avec les blocs Adresse / Contact / Prix.
 *
 * Ne touchent ni à l'API ni à l'état réactif (testables unitairement). Les champs
 * nuls peuvent être OMIS (skip_null_values) → toujours lire avec `?? null`.
 */

import { formatPhoneFR } from '~/shared/utils/phone'
import type {
    CarrierAddressFormDraft,
    CarrierContactFormDraft,
    CarrierMainDraft,
    CarrierPriceFormDraft,
} from '~/modules/transport/types/carrierForm'

/** Référence Hydra embarquée minimale (@id toujours présent). */
export interface HydraRef {
    '@id': string
    [key: string]: unknown
}

/** Une relation peut être embarquée (objet), un IRI nu (chaîne) ou absente. */
export type Relation = HydraRef | string | null | undefined

/** Adresse embarquée (groupe carrier:item:read). */
export interface CarrierAddressRead extends HydraRef {
    id: number
    country?: string | null
    postalCode?: string | null
    city?: string | null
    street?: string | null
    streetComplement?: string | null
}

/** Contact embarqué (groupe carrier:item:read). */
export interface CarrierContactRead extends HydraRef {
    id: number
    firstName?: string | null
    lastName?: string | null
    jobTitle?: string | null
    phonePrimary?: string | null
    phoneSecondary?: string | null
    email?: string | null
}

/** Prix embarqué (groupe carrier:item:read + relations cross-module). */
export interface CarrierPriceRead extends HydraRef {
    id: number
    direction?: string | null
    client?: Relation
    clientDeliveryAddress?: Relation
    departureSite?: Relation
    supplier?: Relation
    supplierSupplyAddress?: Relation
    deliverySite?: Relation
    containerType?: string | null
    pricingUnit?: string | null
    price?: string | null
    priceState?: string | null
}

/**
 * Détail d'un transporteur (`GET /api/carriers/{id}`). Tous les champs optionnels :
 * skip_null_values peut omettre n'importe quelle clé.
 */
export interface CarrierDetail extends HydraRef {
    id: number
    name?: string | null
    certificationType?: string | null
    isChartered?: boolean
    indexationRate?: string | null
    containerType?: string | null
    volumeM3?: string | null
    liotPlates?: string | null
    dischargeDocument?: Relation
    qualimatCarrier?: Relation
    isArchived?: boolean
    addresses?: CarrierAddressRead[]
    contacts?: CarrierContactRead[]
    prices?: CarrierPriceRead[]
}

/** Extrait l'IRI d'une relation (objet embarqué, IRI nu, ou null si absente). */
export function iriOf(relation: Relation): string | null {
    if (relation === null || relation === undefined) {
        return null
    }
    if (typeof relation === 'string') {
        return relation
    }
    return relation['@id'] ?? null
}

/**
 * Libellé d'affichage d'une relation embarquée : `name` (site) à défaut une adresse
 * condensée (voie · CP · ville). Chaîne vide si la relation est un IRI nu / absente.
 */
export function labelOfRelation(relation: Relation): string {
    if (!relation || typeof relation === 'string') {
        return ''
    }
    const name = relation.name as string | undefined
    if (name) {
        return name
    }
    const parts = [relation.street, relation.postalCode, relation.city].filter(Boolean)
    return parts.join(' · ')
}

/** Mappe le détail vers le brouillon du formulaire principal. */
export function mapMainToDraft(detail: CarrierDetail): CarrierMainDraft {
    return {
        name: detail.name ?? '',
        certificationType: detail.certificationType ?? null,
        isChartered: detail.isChartered ?? false,
        indexationRate: detail.indexationRate ?? '',
        containerType: detail.containerType ?? null,
        volumeM3: detail.volumeM3 ?? '',
        liotPlates: detail.liotPlates ?? '',
        dischargeDocumentIri: iriOf(detail.dischargeDocument),
        qualimatCarrierIri: iriOf(detail.qualimatCarrier),
    }
}

/** Mappe une adresse embarquée vers un brouillon. */
export function mapAddressToDraft(address: CarrierAddressRead): CarrierAddressFormDraft {
    return {
        id: address.id,
        country: address.country ?? 'France',
        postalCode: address.postalCode ?? null,
        city: address.city ?? null,
        street: address.street ?? null,
        streetComplement: address.streetComplement ?? null,
    }
}

/** Mappe un contact embarqué vers un brouillon (téléphones formatés XX XX XX XX XX). */
export function mapContactToDraft(contact: CarrierContactRead): CarrierContactFormDraft {
    const secondary = contact.phoneSecondary ?? null
    return {
        id: contact.id,
        firstName: contact.firstName ?? null,
        lastName: contact.lastName ?? null,
        jobTitle: contact.jobTitle ?? null,
        phonePrimary: contact.phonePrimary ? formatPhoneFR(contact.phonePrimary) : null,
        phoneSecondary: secondary ? formatPhoneFR(secondary) : null,
        email: contact.email ?? null,
        hasSecondaryPhone: secondary !== null && secondary !== '',
    }
}

/** Mappe un prix embarqué vers un brouillon (relations en IRI). */
export function mapPriceToDraft(price: CarrierPriceRead): CarrierPriceFormDraft {
    const direction = price.direction === 'CLIENT' || price.direction === 'FOURNISSEUR'
        ? price.direction
        : null
    return {
        id: price.id,
        direction,
        clientIri: iriOf(price.client),
        clientDeliveryAddressIri: iriOf(price.clientDeliveryAddress),
        departureSiteIri: iriOf(price.departureSite),
        supplierIri: iriOf(price.supplier),
        supplierSupplyAddressIri: iriOf(price.supplierSupplyAddress),
        deliverySiteIri: iriOf(price.deliverySite),
        containerType: price.containerType ?? null,
        pricingUnit: price.pricingUnit ?? null,
        price: price.price ?? null,
        priceState: price.priceState ?? null,
    }
}

/** Bouton « Modifier » : visible avec la permission `manage` (Admin / Bureau). */
export function canEditCarrier(can: (code: string) => boolean): boolean {
    return can('transport.carriers.manage')
}

/** Bouton « Archiver » : permission archive ET transporteur encore actif (Admin seul). */
export function showArchiveAction(can: (code: string) => boolean, isArchived: boolean): boolean {
    return can('transport.carriers.archive') && !isArchived
}

/** Bouton « Restaurer » : permission archive ET transporteur déjà archivé (Admin seul). */
export function showRestoreAction(can: (code: string) => boolean, isArchived: boolean): boolean {
    return can('transport.carriers.archive') && isArchived
}
