import { useState, type FormEvent } from 'react';
import type { InvitationResponse, UserAdmin } from '@siop/shared';
import {
  useCreateTeam,
  useInviteUser,
  useLocations,
  useResendInvitation,
  useRoles,
  useTeams,
  useUpdateUser,
  useUsers,
} from '@/api/referentiel';
import { usePermissions } from '@/auth/use-permissions';
import { Avatar, initialsOf } from '@/components/avatar';
import { Button } from '@/components/ui/button';
import { Modale } from '@/components/ui/modale';

/** Écran 6 des maquettes R1 : personnes (invitation par lien 7 j, jamais de
 *  mot de passe créé pour autrui) et équipes par zone. */
export default function PagePersonnes() {
  const { data: users } = useUsers();
  const { data: teams } = useTeams();
  const { can } = usePermissions();
  const [modaleInvitation, setModaleInvitation] = useState(false);
  const [modaleEquipe, setModaleEquipe] = useState(false);
  const [lien, setLien] = useState<InvitationResponse | null>(null);
  const renvoi = useResendInvitation();

  return (
    <>
      <div className="entete-page">
        <h1>Personnes & équipes</h1>
        <div className="actions">
          {can('PEOPLE_TEAMS', 'create') ? (
            <Button variant="prim" onClick={() => setModaleInvitation(true)}>
              + Inviter
            </Button>
          ) : null}
        </div>
      </div>
      <div className="carte" style={{ padding: 0 }}>
        <div className="table">
          <table>
            <thead>
              <tr>
                <th>Personne</th>
                <th>Rôle</th>
                <th>Équipe</th>
                <th>Taux horaire</th>
                <th>Sites</th>
                <th>Statut</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {(users ?? []).map((u) => (
                <tr key={u.id}>
                  <td>
                    <div className="flex items-center gap-[9px]">
                      <Avatar
                        initials={initialsOf(u.displayName)}
                        roleName={u.role.name}
                        className="h-[26px] w-[26px] text-[10.5px]"
                      />
                      <div>
                        <b>{u.displayName}</b>
                        <span className="sous">{u.email}</span>
                      </div>
                    </div>
                  </td>
                  <td>{u.role.name}</td>
                  <td>{u.teams.map((t) => t.name).join(', ') || '—'}</td>
                  <td>
                    <CelluleTaux
                      userId={u.id}
                      taux={u.hourlyRate}
                      editable={can('PEOPLE_TEAMS', 'edit')}
                    />
                  </td>
                  <td>
                    {u.role.name === 'Demandeur' ? (
                      <CelluleSites utilisateur={u} editable={can('PEOPLE_TEAMS', 'edit')} />
                    ) : (
                      '—'
                    )}
                  </td>
                  <td>
                    {u.status === 'active' ? (
                      <span className="st termine">Actif</span>
                    ) : u.status === 'invited' ? (
                      <span className="st attente">Invitation envoyée</span>
                    ) : (
                      <span className="st annule">Désactivé</span>
                    )}
                  </td>
                  <td>
                    {u.status === 'invited' && can('PEOPLE_TEAMS', 'edit') ? (
                      <Button
                        variant="ghost"
                        className="px-2 py-1 text-[12px]"
                        disabled={renvoi.isPending}
                        onClick={() => renvoi.mutate(u.id, { onSuccess: setLien })}
                      >
                        Renvoyer le lien
                      </Button>
                    ) : null}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
      <div className="carte">
        <h2>Équipes</h2>
        <div className="equipes">
          {(teams ?? []).map((t) => (
            <div className="equipe" key={t.id}>
              <b>{t.name}</b>
              <span className="zone">{t.description ?? '—'}</span>
              <div className="avatars">
                {t.members.map((m) => (
                  <Avatar
                    key={m.id}
                    initials={m.initials}
                    roleName={m.roleName}
                    className="h-6 w-6 text-[10px]"
                  />
                ))}
                {t.members.length === 0 ? (
                  <span className="text-[12px] text-encre-3">aucun membre</span>
                ) : null}
              </div>
            </div>
          ))}
          {can('PEOPLE_TEAMS', 'create') ? (
            <button
              type="button"
              className="equipe items-center justify-center text-encre-3"
              style={{ borderStyle: 'dashed', cursor: 'pointer' }}
              onClick={() => setModaleEquipe(true)}
            >
              <b style={{ fontWeight: 600 }}>+ Nouvelle équipe</b>
            </button>
          ) : null}
        </div>
      </div>

      <ModaleInvitation
        ouverte={modaleInvitation}
        surFermeture={setModaleInvitation}
        surLien={setLien}
      />
      <ModaleEquipe ouverte={modaleEquipe} surFermeture={setModaleEquipe} />
      <ModaleLien lien={lien} surFermeture={() => setLien(null)} />
    </>
  );
}

/** Taux horaire courant (R3) — appliqué aux futures saisies de temps ; les
 *  temps déjà valorisés gardent leur taux figé. */
function CelluleTaux({
  userId,
  taux,
  editable,
}: {
  userId: string;
  taux: number | null;
  editable: boolean;
}) {
  const maj = useUpdateUser();
  const [edition, setEdition] = useState(false);

  if (!edition) {
    return (
      <span className="num">
        {taux != null ? `${new Intl.NumberFormat('fr-FR').format(taux)} MAD/h` : '—'}
        {editable ? (
          <Button
            variant="ghost"
            className="ml-1 px-2 py-0.5 text-[12px]"
            aria-label="Modifier le taux horaire"
            onClick={() => setEdition(true)}
          >
            ✎
          </Button>
        ) : null}
      </span>
    );
  }
  return (
    <input
      type="number"
      min={0}
      step="0.01"
      autoFocus
      defaultValue={taux ?? ''}
      aria-label="Nouveau taux horaire (MAD/h)"
      className="num w-24 rounded-lg border border-bordure-forte bg-surface px-2 py-1 text-encre"
      disabled={maj.isPending}
      onBlur={(e) => {
        const valeur = e.target.value.trim();
        const nombre = Number(valeur);
        if (valeur && nombre > 0 && nombre !== taux) {
          maj.mutate({ id: userId, hourlyRate: nombre }, { onSettled: () => setEdition(false) });
        } else {
          setEdition(false);
        }
      }}
      onKeyDown={(e) => {
        if (e.key === 'Enter') e.currentTarget.blur();
        if (e.key === 'Escape') setEdition(false);
      }}
    />
  );
}

/** Sites autorisés en signalement (R6.6) — un Demandeur ne choisit son
 *  équipement que parmi ceux de ses sites rattachés (web + mobile, même
 *  filtre côté API : `/assets/options`). */
function CelluleSites({
  utilisateur,
  editable,
}: {
  utilisateur: UserAdmin;
  editable: boolean;
}) {
  const [modale, setModale] = useState(false);
  return (
    <>
      <span className="num">
        {utilisateur.assignedSites.map((s) => s.name).join(', ') || '—'}
        {editable ? (
          <Button
            variant="ghost"
            className="ml-1 px-2 py-0.5 text-[12px]"
            aria-label="Modifier les sites rattachés"
            onClick={() => setModale(true)}
          >
            ✎
          </Button>
        ) : null}
      </span>
      <ModaleSites utilisateur={utilisateur} ouverte={modale} surFermeture={setModale} />
    </>
  );
}

function ModaleSites({
  utilisateur,
  ouverte,
  surFermeture,
}: {
  utilisateur: UserAdmin;
  ouverte: boolean;
  surFermeture: (o: boolean) => void;
}) {
  const { data: locations } = useLocations();
  const sites = (locations ?? []).filter((l) => l.parentId === null);
  const maj = useUpdateUser();
  const [coches, setCoches] = useState<string[]>(() => utilisateur.assignedSites.map((s) => s.id));

  const surEnvoi = (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    maj.mutate(
      { id: utilisateur.id, locationIds: coches },
      { onSuccess: () => surFermeture(false) },
    );
  };

  return (
    <Modale titre={`Sites de ${utilisateur.displayName}`} ouverte={ouverte} surFermeture={surFermeture}>
      <form onSubmit={surEnvoi} className="flex flex-col gap-3">
        <div className="flex flex-col gap-1">
          {sites.map((s) => (
            <label key={s.id} className="flex items-center gap-2 text-[13px]">
              <input
                type="checkbox"
                checked={coches.includes(s.id)}
                onChange={(e) =>
                  setCoches((c) => (e.target.checked ? [...c, s.id] : c.filter((id) => id !== s.id)))
                }
              />
              {s.name}
            </label>
          ))}
        </div>
        <p className="note-douce">
          Le signalement se limite aux sites cochés ci-dessus. Aucun site coché = aucune
          restriction (accès au parc complet, comportement historique).
        </p>
        {maj.isError ? <p className="erreur-form" role="alert">{maj.error.message}</p> : null}
        <div className="pied">
          <Button onClick={() => surFermeture(false)}>Annuler</Button>
          <Button type="submit" variant="prim" disabled={maj.isPending}>Enregistrer</Button>
        </div>
      </form>
    </Modale>
  );
}

function ModaleInvitation({
  ouverte,
  surFermeture,
  surLien,
}: {
  ouverte: boolean;
  surFermeture: (o: boolean) => void;
  surLien: (l: InvitationResponse) => void;
}) {
  const { data: roles } = useRoles();
  const { data: teams } = useTeams();
  const { data: locations } = useLocations();
  const invitation = useInviteUser();
  const [roleId, setRoleId] = useState('');
  const [sitesCoches, setSitesCoches] = useState<string[]>([]);
  const roleName = roles?.find((r) => r.id === roleId)?.name;
  const sites = (locations ?? []).filter((l) => l.parentId === null);

  const surEnvoi = (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const donnees = new FormData(e.currentTarget);
    const teamId = String(donnees.get('teamId'));
    invitation.mutate(
      {
        email: String(donnees.get('email')),
        displayName: String(donnees.get('displayName')),
        roleId: String(donnees.get('roleId')),
        teamIds: teamId ? [teamId] : undefined,
        locationIds: sitesCoches.length ? sitesCoches : undefined,
      },
      {
        onSuccess: (reponse) => {
          surFermeture(false);
          setRoleId('');
          setSitesCoches([]);
          surLien(reponse);
        },
      },
    );
  };

  return (
    <Modale titre="Inviter une personne" ouverte={ouverte} surFermeture={surFermeture}>
      <form onSubmit={surEnvoi} className="flex flex-col gap-3">
        <div className="champ">
          <label htmlFor="inv-nom">Nom complet *</label>
          <input id="inv-nom" name="displayName" required placeholder="Prénom Nom" />
        </div>
        <div className="champ">
          <label htmlFor="inv-email">Email professionnel *</label>
          <input id="inv-email" name="email" type="email" required placeholder="prenom.nom@spelev.ma" />
        </div>
        <div className="form-grille">
          <div className="champ">
            <label htmlFor="inv-role">Rôle *</label>
            <select
              id="inv-role"
              name="roleId"
              required
              value={roleId}
              onChange={(e) => setRoleId(e.target.value)}
            >
              <option value="" disabled>Choisir…</option>
              {(roles ?? []).map((r) => (
                <option key={r.id} value={r.id}>{r.name}</option>
              ))}
            </select>
          </div>
          <div className="champ">
            <label htmlFor="inv-equipe">Équipe (optionnel)</label>
            <select id="inv-equipe" name="teamId" defaultValue="">
              <option value="">—</option>
              {(teams ?? []).map((t) => (
                <option key={t.id} value={t.id}>{t.name}</option>
              ))}
            </select>
          </div>
        </div>
        {roleName === 'Demandeur' ? (
          <div className="champ">
            <label>Sites autorisés en signalement (optionnel)</label>
            <div className="flex flex-col gap-1">
              {sites.map((s) => (
                <label key={s.id} className="flex items-center gap-2 text-[13px]">
                  <input
                    type="checkbox"
                    checked={sitesCoches.includes(s.id)}
                    onChange={(e) =>
                      setSitesCoches((c) =>
                        e.target.checked ? [...c, s.id] : c.filter((id) => id !== s.id),
                      )
                    }
                  />
                  {s.name}
                </label>
              ))}
            </div>
            <p className="note-douce">
              Aucun site coché = aucune restriction (accès au parc complet).
            </p>
          </div>
        ) : null}
        <p className="note-douce">
          La personne recevra un <b>lien d'activation valable 7 jours</b> pour choisir
          son mot de passe. Aucun compte n'est actif avant cela.
        </p>
        {invitation.isError ? (
          <p className="erreur-form" role="alert">{invitation.error.message}</p>
        ) : null}
        <div className="pied">
          <Button onClick={() => surFermeture(false)}>Annuler</Button>
          <Button type="submit" variant="prim" disabled={invitation.isPending}>
            Envoyer l'invitation
          </Button>
        </div>
      </form>
    </Modale>
  );
}

/** L'envoi d'email n'existe pas encore : le lien se copie ici (décision R1). */
function ModaleLien({
  lien,
  surFermeture,
}: {
  lien: InvitationResponse | null;
  surFermeture: () => void;
}) {
  const [copie, setCopie] = useState(false);
  if (!lien) return null;
  const url = `${window.location.origin}/activation?token=${lien.activationToken}`;
  return (
    <Modale titre="Lien d'activation émis" ouverte surFermeture={surFermeture}>
      <p className="text-[13px] text-encre-2">
        Transmettez ce lien à la personne (valable jusqu'au{' '}
        {new Intl.DateTimeFormat('fr-FR', { dateStyle: 'long' }).format(new Date(lien.expiresAt))}) :
      </p>
      <div className="lien-copiable" data-testid="lien-activation">{url}</div>
      <div className="pied">
        <Button
          onClick={() => {
            void navigator.clipboard.writeText(url);
            setCopie(true);
          }}
        >
          {copie ? 'Copié ✓' : 'Copier le lien'}
        </Button>
        <Button variant="prim" onClick={surFermeture}>Fermer</Button>
      </div>
    </Modale>
  );
}

function ModaleEquipe({
  ouverte,
  surFermeture,
}: {
  ouverte: boolean;
  surFermeture: (o: boolean) => void;
}) {
  const creation = useCreateTeam();
  const surEnvoi = (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const donnees = new FormData(e.currentTarget);
    creation.mutate(
      {
        name: String(donnees.get('name')),
        description: String(donnees.get('description')) || undefined,
      },
      { onSuccess: () => surFermeture(false) },
    );
  };
  return (
    <Modale titre="Nouvelle équipe" ouverte={ouverte} surFermeture={surFermeture}>
      <form onSubmit={surEnvoi} className="flex flex-col gap-3">
        <div className="champ">
          <label htmlFor="eq-nom">Nom *</label>
          <input id="eq-nom" name="name" required placeholder="Ex. : Rabat Agdal" />
        </div>
        <div className="champ">
          <label htmlFor="eq-desc">Zone couverte</label>
          <input id="eq-desc" name="description" placeholder="Sites couverts…" />
        </div>
        {creation.isError ? (
          <p className="erreur-form" role="alert">{creation.error.message}</p>
        ) : null}
        <div className="pied">
          <Button onClick={() => surFermeture(false)}>Annuler</Button>
          <Button type="submit" variant="prim" disabled={creation.isPending}>Créer</Button>
        </div>
      </form>
    </Modale>
  );
}
