import { ShieldAlert, ShieldCheck, ShieldQuestion, UserCheck, UserPlus } from 'lucide-react';

export type PlanningKind = 'menage' | 'verif';

export interface PlanningUser {
    id: number;
    name: string;
}

/**
 * Ce que la carte reçoit du serveur pour la planification.
 *
 * `userVerif` porte un id — mais jusqu'à TL-269 le modèle déclarait une relation
 * du MÊME NOM, qui écrasait l'attribut dès qu'un contrôleur la préchargeait. La
 * relation s'appelle désormais `verifiedBy()`, et ce type reste tolérant : une
 * base servie par du code plus ancien peut encore renvoyer un objet.
 */
export interface PlanningData {
    userPlaned?: unknown;
    userVerif?: unknown;
    isVerif?: string | null;
}

/**
 * Trois états, une seule grammaire de couleur dans toute la carte :
 * vert = c'est fait, ambre = quelqu'un s'en occupe, ardoise = personne.
 */
const TONES = {
    done: 'bg-emerald-700 text-white',
    pending: 'bg-amber-500 text-amber-950',
    none: 'bg-slate-600 text-white',
} as const;

const ICONS = {
    menage: { done: UserCheck, pending: UserCheck, none: UserPlus },
    verif: { done: ShieldCheck, pending: ShieldQuestion, none: ShieldAlert },
} as const;

/**
 * Les identifiants des personnes affectées au ménage.
 *
 * `plannings.userPlaned` est castée en tableau par le modèle, mais on a vu la
 * valeur arriver en chaîne JSON selon le chemin d'écriture — d'où la tolérance.
 */
function planedIds(raw: unknown): number[] {
    if (Array.isArray(raw)) {
        return raw.map(Number).filter((id) => Number.isFinite(id));
    }

    if (typeof raw === 'string' && raw.trim() !== '') {
        try {
            const parsed: unknown = JSON.parse(raw);
            return Array.isArray(parsed) ? parsed.map(Number).filter((id) => Number.isFinite(id)) : [];
        } catch {
            return [];
        }
    }

    return [];
}

/**
 * Qui s'occupe du ménage, résolu depuis la liste envoyée à la page.
 */
function menageAssignee(planning: PlanningData | null | undefined, users: PlanningUser[]): string | null {
    const ids = planedIds(planning?.userPlaned);

    if (ids.length === 0) {
        return null;
    }

    const first = users.find((user) => Number(user.id) === ids[0])?.name ?? `#${ids[0]}`;

    return ids.length > 1 ? `${first} +${ids.length - 1}` : first;
}

/**
 * Pastille de planification — ménage assigné, ou vérification d'arrivée assignée
 * puis confirmée (TL-269).
 *
 * L'information existait, mais **enterrée dans le menu ☰** : le commentaire de
 * TL-285 affirmait que l'icône restait visible sur le déclencheur, ce qui n'était
 * pas le cas. Mesuré le 2026-09-10 : plus une seule planification créée depuis 15
 * jours, et 0 des 312 réservations en cours ou à venir n'en avait une. Une
 * information que personne ne voit est une information que personne ne tient.
 *
 * Pour la vérification, la pastille montre **l'ASSIGNÉE** (l'intention) et passe
 * au vert quand elle a confirmé (`isVerif`). C'est le sens que l'ancien champ
 * n'avait pas : il ne savait dire que « X a confirmé », au passé, donc personne
 * ne savait à qui c'était échu.
 *
 * Boîte fixe (hauteur + largeur minimale) pour que les états s'alignent d'une
 * carte à l'autre — sans quoi l'œil ne peut pas balayer une rangée.
 */
export default function PlanningBadge({
    kind,
    planning,
    users,
    assignedToName,
    translations,
    onOpen,
}: {
    kind: PlanningKind;
    planning?: PlanningData | null;
    /** Personnes assignables, déjà envoyées à la page (menageUsers). */
    users?: PlanningUser[];
    /** Nom de l'assignée de la vérification, résolu côté serveur (CardDTO). */
    assignedToName?: string | null;
    translations: Record<string, Record<string, string>>;
    /** Ouvre la fenêtre de planification ; absent = pastille en lecture seule. */
    onOpen?: () => void;
}) {
    const who = kind === 'menage' ? menageAssignee(planning, users ?? []) : (assignedToName ?? null);
    const verified = kind === 'verif' && planning?.isVerif === 'Oui';

    const state: keyof typeof TONES = !who ? 'none' : kind === 'menage' || verified ? 'done' : 'pending';

    const labelKey = kind === 'menage' ? 'menage_label' : 'verif_label';
    const todoKey = kind === 'menage' ? 'menage_unassigned' : 'verif_unassigned';
    const label = `${translations.dashboard[labelKey]}: ${who ?? translations.dashboard[todoKey]}`;

    const Icon = ICONS[kind][state];
    const shape = `inline-flex h-6 min-w-[9rem] shrink-0 items-center gap-1.5 rounded-full px-2.5 text-xs font-medium ${TONES[state]}`;

    if (!onOpen) {
        return (
            <span className={shape} title={label}>
                <Icon className="h-3.5 w-3.5 shrink-0" />
                <span className="truncate">{label}</span>
            </span>
        );
    }

    return (
        <button type="button" onClick={onOpen} title={label} className={`${shape} cursor-pointer transition hover:brightness-110`}>
            <Icon className="h-3.5 w-3.5 shrink-0" />
            <span className="truncate">{label}</span>
        </button>
    );
}
