import { useState, type FormEvent } from 'react';
import { Link, useParams } from 'react-router-dom';
import {
  BILAN_FIELD_LABELS,
  REQUIRED_BILAN_FIELDS,
  WORK_ORDER_TYPE_LABELS,
  type BilanField,
  type WorkOrderDetail,
  type WorkOrderStatus,
} from '@siop/shared';
import {
  useCommentWorkOrder,
  usePatchChecklist,
  useReferenceValues,
  useSetAssignees,
  useTransitionWorkOrder,
  useUpsertReport,
  useWorkOrder,
} from '@/api/exploitation';
import { useUsers } from '@/api/referentiel';
import { usePermissions } from '@/auth/use-permissions';
import { Avatar } from '@/components/avatar';
import { PrioriteOT, StatutOT } from '@/components/chips-ot';
import { Button } from '@/components/ui/button';
import { formatDateFr } from '@/lib/lieux';

const BOUTONS_TRANSITION: Record<WorkOrderStatus, { libelle: string; variant?: 'prim' | 'succes' | 'dangerLeger' | 'ghost' }> = {
  IN_PROGRESS: { libelle: 'Démarrer', variant: 'prim' },
  ON_HOLD: { libelle: 'En attente', variant: 'ghost' },
  DONE: { libelle: "Clôturer l'intervention", variant: 'succes' },
  CANCELLED: { libelle: 'Annuler', variant: 'dangerLeger' },
  OPEN: { libelle: 'Rouvrir' },
};

/** Écran 4 validé R0 (+ checklist maquette R2) : tout le carnet sur un écran. */
export default function PageFicheOT() {
  const { id } = useParams<{ id: string }>();
  const { data: ot } = useWorkOrder(id);
  const { can } = usePermissions();
  const transition = useTransitionWorkOrder(id ?? '');

  if (!ot) return null;
  const peutEditer = can('WORK_ORDERS', 'edit');
  const cloturable = ot.closureBlockers.length === 0;

  return (
    <>
      <div className="filajout">
        <Link to="/ot">Ordres de travail</Link> / {ot.reference}
      </div>
      <div className="entete-page">
        <h1>{ot.title}</h1>
        <StatutOT statut={ot.status} />
        <div className="actions">
          {peutEditer
            ? ot.allowedTransitions.map((cible) => {
                const bouton = BOUTONS_TRANSITION[cible];
                const bloquee = cible === 'DONE' && !cloturable;
                return (
                  <Button
                    key={cible}
                    variant={bouton.variant}
                    disabled={transition.isPending || bloquee}
                    title={bloquee ? ot.closureBlockers.join(' ; ') : undefined}
                    onClick={() => {
                      const commentaire =
                        cible === 'CANCELLED'
                          ? window.prompt('Motif d’annulation (visible dans l’activité) :') ?? undefined
                          : undefined;
                      if (cible === 'CANCELLED' && !commentaire) return;
                      transition.mutate({ to: cible, comment: commentaire });
                    }}
                  >
                    {bouton.libelle}
                  </Button>
                );
              })
            : null}
        </div>
      </div>
      {transition.isError ? (
        <p className="erreur-form" role="alert">{transition.error.message}</p>
      ) : null}
      <div className="grille-2">
        <CarteIntervention ot={ot} peutEditer={peutEditer} />
        <CarteActivite ot={ot} peutEditer={peutEditer} />
      </div>
      <div className="grille-2">
        <div className="flex flex-col gap-4">
          {ot.checklist.length > 0 ? <CarteChecklist ot={ot} peutEditer={peutEditer} /> : null}
          <CarteBilan ot={ot} peutEditer={peutEditer} />
        </div>
        <div className="flex flex-col gap-4">
          <div className="carte" style={{ borderStyle: 'dashed' }}>
            <h2>Pièces & main-d'œuvre</h2>
            <p className="text-encre-3">Consommations et coûts arrivent avec la gestion (R3).</p>
          </div>
          <div className="carte" style={{ borderStyle: 'dashed' }}>
            <h2>Documents</h2>
            <p className="text-encre-3">Photos et pièces jointes arrivent avec la bibliothèque (R3).</p>
          </div>
        </div>
      </div>
    </>
  );
}

function CarteIntervention({ ot, peutEditer }: { ot: WorkOrderDetail; peutEditer: boolean }) {
  const { data: users } = useUsers();
  const assignation = useSetAssignees(ot.id);
  const [enAssignation, setEnAssignation] = useState(false);
  const techniciens = (users ?? []).filter(
    (u) => u.status === 'active' && u.role.name.startsWith('Technicien'),
  );

  return (
    <div className="carte">
      <h2>Intervention</h2>
      <dl className="infos">
        <dt>N°</dt>
        <dd className="num">{ot.reference} · {WORK_ORDER_TYPE_LABELS[ot.type]}</dd>
        <dt>Équipement</dt>
        <dd>
          <Link to={`/ascenseurs/${ot.assetId}`} style={{ color: 'var(--primaire)', fontWeight: 600 }}>
            Ascenseur {ot.assetReference}
          </Link>{' '}
          — {ot.siteName}
        </dd>
        <dt>Priorité</dt>
        <dd><PrioriteOT priorite={ot.priority} /></dd>
        <dt>Échéance</dt>
        <dd className="num">{formatDateFr(ot.dueDate)}</dd>
        <dt>Assignés</dt>
        <dd className="flex items-center gap-2">
          {ot.assignees.length ? (
            <>
              <span className="avatars">
                {ot.assignees.map((a) => (
                  <Avatar key={a.id} initials={a.initials} className="h-6 w-6 text-[10px]" />
                ))}
              </span>
              {ot.assignees.map((a) => a.displayName).join(', ')}
            </>
          ) : (
            '—'
          )}
          {peutEditer ? (
            <Button
              variant="ghost"
              className="px-2 py-1 text-[12px]"
              onClick={() => setEnAssignation((v) => !v)}
            >
              + Assigner
            </Button>
          ) : null}
        </dd>
        {ot.request ? (
          <>
            <dt>Demande liée</dt>
            <dd>
              <span className="num">{ot.request.reference}</span> — {ot.request.requesterLabel}
            </dd>
          </>
        ) : null}
      </dl>
      {enAssignation ? (
        <div className="mt-3 flex items-center gap-2">
          <select
            aria-label="Choisir un technicien"
            className="flex-1 rounded-lg border border-bordure-forte bg-surface p-2 text-encre"
            defaultValue=""
            onChange={(e) => {
              if (!e.target.value) return;
              assignation.mutate(
                { assigneeIds: [...new Set([...ot.assignees.map((a) => a.id), e.target.value])] },
                { onSuccess: () => setEnAssignation(false) },
              );
            }}
          >
            <option value="" disabled>Choisir un technicien…</option>
            {techniciens.map((t) => (
              <option key={t.id} value={t.id}>{t.displayName}</option>
            ))}
          </select>
          {ot.assignees.length ? (
            <Button
              variant="ghost"
              className="text-[12px]"
              onClick={() =>
                assignation.mutate({ assigneeIds: [] }, { onSuccess: () => setEnAssignation(false) })
              }
            >
              Tout retirer
            </Button>
          ) : null}
        </div>
      ) : null}
    </div>
  );
}

const KIND_LABELS: Record<string, string> = {
  CREATED: 'OT créé',
  GENERATED: 'Généré',
  FROM_REQUEST: 'Créé depuis une demande',
  STATUS_CHANGED: 'Changement d’état',
  ASSIGNED: 'Assignation',
  COMMENT: 'Commentaire',
};

function CarteActivite({ ot, peutEditer }: { ot: WorkOrderDetail; peutEditer: boolean }) {
  const commentaire = useCommentWorkOrder(ot.id);
  const surEnvoi = (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const form = e.currentTarget;
    const message = String(new FormData(form).get('message') ?? '').trim();
    if (!message) return;
    commentaire.mutate(message, { onSuccess: () => form.reset() });
  };
  return (
    <div className="carte">
      <h2>Activité</h2>
      {peutEditer ? (
        <form onSubmit={surEnvoi} className="mb-3 flex gap-2">
          <input
            name="message"
            aria-label="Commenter"
            placeholder="Commenter…"
            className="flex-1 rounded-lg border border-bordure-forte bg-surface px-3 py-2 text-encre"
          />
          <Button type="submit" disabled={commentaire.isPending}>Publier</Button>
        </form>
      ) : null}
      <ul className="chrono">
        {ot.events.map((e) => (
          <li key={e.id} className="fait">
            {e.kind === 'COMMENT' ? (
              <>Commentaire {e.by ? <b>{e.by.displayName}</b> : null} : « {e.message} »</>
            ) : (
              <>
                <b>{KIND_LABELS[e.kind] ?? e.kind}</b>
                {e.message ? <> — {e.message}</> : null}
              </>
            )}
            <br />
            <span className="quand">
              {new Intl.DateTimeFormat('fr-FR', { dateStyle: 'medium', timeStyle: 'short' }).format(new Date(e.createdAt))}
              {e.by && e.kind !== 'COMMENT' ? ` · ${e.by.displayName}` : ''}
            </span>
          </li>
        ))}
      </ul>
    </div>
  );
}

function CarteChecklist({ ot, peutEditer }: { ot: WorkOrderDetail; peutEditer: boolean }) {
  const patch = usePatchChecklist(ot.id);
  const traitees = ot.checklist.filter((c) => c.state !== 'PENDING').length;
  return (
    <div className="carte">
      <h2>
        Checklist du mois{' '}
        <span style={{ color: 'var(--encre-3)', textTransform: 'none', letterSpacing: 0 }}>
          — {traitees} / {ot.checklist.length} traitées
        </span>
      </h2>
      {ot.checklist.map((item) => (
        <div className="check" key={item.id}>
          <button
            type="button"
            className={`coche ${item.state === 'DONE' ? 'ok' : item.state === 'NA' ? 'na' : ''}`}
            aria-label={`${item.label} — ${item.state === 'PENDING' ? 'marquer Fait (clic) ou N-A (double clic)' : 'remettre à faire'}`}
            disabled={!peutEditer || patch.isPending}
            onClick={() =>
              patch.mutate({
                itemId: item.id,
                state: item.state === 'PENDING' ? 'DONE' : item.state === 'DONE' ? 'NA' : 'PENDING',
              })
            }
          >
            {item.state === 'DONE' ? '✓' : item.state === 'NA' ? 'N-A' : ''}
          </button>
          {item.label}
          <span className="qui-fait">
            {item.doneBy
              ? `${item.doneBy.displayName.split(' ')[0]} · ${new Intl.DateTimeFormat('fr-FR', { timeStyle: 'short' }).format(new Date(item.doneAt!))}`
              : '—'}
          </span>
        </div>
      ))}
      {ot.checklist.some((c) => c.state === 'PENDING') ? (
        <p className="avertissement">
          ⚠ La clôture reste bloquée : chaque tâche doit être <b>Fait</b> ou <b>N-A</b>.
        </p>
      ) : null}
    </div>
  );
}

const CHAMPS_BILAN: { champ: BilanField; cle: keyof NonNullable<WorkOrderDetail['report']> & string; dto: string }[] = [
  { champ: 'DOOR_STATE', cle: 'doorState', dto: 'doorStateId' },
  { champ: 'CABIN_POSITION', cle: 'cabinPosition', dto: 'cabinPositionId' },
  { champ: 'ANOMALY', cle: 'anomaly', dto: 'anomalyId' },
  { champ: 'EXTERNAL_CAUSE', cle: 'externalCause', dto: 'externalCauseId' },
  { champ: 'ACTION_TAKEN', cle: 'actionTaken', dto: 'actionTakenId' },
  { champ: 'COMPONENT_CONCERNED', cle: 'componentConcerned', dto: 'componentConcernedId' },
];

function CarteBilan({ ot, peutEditer }: { ot: WorkOrderDetail; peutEditer: boolean }) {
  const { data: valeurs } = useReferenceValues();
  const maj = useUpsertReport(ot.id);
  const bloqueurBilan = ot.closureBlockers.find((b) => b.includes('bilan'));

  return (
    <div className="carte">
      <h2>
        Bilan d'intervention{' '}
        <span style={{ color: 'var(--encre-3)', textTransform: 'none', letterSpacing: 0 }}>
          — requis pour clôturer
        </span>
      </h2>
      <div className="bilan">
        {CHAMPS_BILAN.map(({ champ, cle, dto }) => {
          const options = (valeurs ?? []).filter((v) => v.field === champ && v.isActive);
          const valeur = ot.report?.[cle as 'doorState'] ?? null;
          const requis = REQUIRED_BILAN_FIELDS.includes(champ);
          return (
            <div className="champ-b" key={champ}>
              <label htmlFor={`bilan-${champ}`}>
                {BILAN_FIELD_LABELS[champ]} {requis ? <em>*</em> : null}
              </label>
              <select
                id={`bilan-${champ}`}
                disabled={!peutEditer || maj.isPending || ot.status === 'DONE' || ot.status === 'CANCELLED'}
                value={valeur?.id ?? ''}
                onChange={(e) => maj.mutate({ [dto]: e.target.value || null })}
              >
                <option value="">Sélectionner…</option>
                {options.map((o) => (
                  <option key={o.id} value={o.id}>{o.label}</option>
                ))}
              </select>
            </div>
          );
        })}
      </div>
      {bloqueurBilan && ot.status !== 'DONE' && ot.status !== 'CANCELLED' ? (
        <p className="avertissement">⚠ {bloqueurBilan} — la clôture restera bloquée.</p>
      ) : null}
      {maj.isError ? <p className="erreur-form" role="alert">{maj.error.message}</p> : null}
    </div>
  );
}
