import { cn } from '@/lib/utils';
import type { ActivityActor, ActivityEntry, ActivityEvent, ActivityTeamState } from '@/types/activity';
import { Bot } from 'lucide-react';
import { Fragment } from 'react';
import { eventTone, fill, subjectLabel, TEAM_STATE_CHIP_CLASSES, TONE_CHIP_CLASSES, type Translate } from './activity-format';

// Déclaré dans CHAQUE fichier : `ActivityTranslationsTest` résout `t(NS, …)`
// par fichier et ne suit pas les imports.
const NS = 'activity';

/** Libellé court d'une action, pour sa pastille. */
export function eventLabel(event: ActivityEvent, t: Translate): string {
    switch (event) {
        case 'created':
            return t(NS, 'event_created', 'Création');
        case 'updated':
            return t(NS, 'event_updated', 'Modification');
        case 'deleted':
            return t(NS, 'event_deleted', 'Suppression');
        case 'restored':
            return t(NS, 'event_restored', 'Restauration');
        case 'login':
            return t(NS, 'event_login', 'Connexion');
        case 'logout':
            return t(NS, 'event_logout', 'Déconnexion');
        case 'login_failed':
            return t(NS, 'event_login_failed', 'Échec de connexion');
        case 'permissions_updated':
            return t(NS, 'event_permissions_updated', 'Droits modifiés');
        case 'exported':
            return t(NS, 'event_exported', 'Export');
        default:
            return event;
    }
}

const CHIP_BASE = 'inline-flex shrink-0 items-center rounded-md border px-2 py-0.5 text-xs font-medium whitespace-nowrap';

/** Pastille d'action : la couleur ne dit que création / suppression / sensible. */
export function ActionChip({ event, t, className }: { event: ActivityEvent; t: Translate; className?: string }) {
    return <span className={cn(CHIP_BASE, TONE_CHIP_CLASSES[eventTone(event)], className)}>{eventLabel(event, t)}</span>;
}

/** Pastille d'état d'un membre (onglet Équipe). */
export function TeamStateChip({ state, t }: { state: ActivityTeamState; t: Translate }) {
    const labels: Record<ActivityTeamState, string> = {
        active: t(NS, 'state_active', 'Actif'),
        quiet: t(NS, 'state_quiet', 'Calme'),
        inactive: t(NS, 'state_inactive', 'Inactif'),
        never: t(NS, 'state_never', 'Jamais vu'),
    };

    return <span className={cn(CHIP_BASE, TEAM_STATE_CHIP_CLASSES[state])}>{labels[state]}</span>;
}

/**
 * Équipe de l'acteur quand elle n'est pas celle du lecteur (« Siège » vu d'une
 * franchise, nom de la franchise vu du siège). Contour neutre : c'est une
 * provenance, pas un signal.
 */
export function ActorTeamBadge({ team, t, className }: { team: string | null; t: Translate; className?: string }) {
    if (!team) return null;

    return (
        <span
            title={fill(t(NS, 'actor_team_title', 'Équipe : :team'), { team })}
            className={cn(
                'text-muted-foreground inline-flex items-center rounded border px-1 py-px align-[1px] text-[10px] leading-none font-medium whitespace-nowrap',
                className,
            )}
        >
            {team}
        </span>
    );
}

/**
 * Avatar NEUTRE : initiales sur fond gris, un robot pour le système. Aucune
 * couleur par personne — la couleur est réservée au sens de l'action.
 */
export function ActorAvatar({ actor, size = 'md' }: { actor: Pick<ActivityActor, 'initials' | 'is_system' | 'name'>; size?: 'sm' | 'md' }) {
    return (
        <span
            aria-hidden="true"
            className={cn(
                'bg-muted text-muted-foreground flex shrink-0 items-center justify-center rounded-full border font-semibold uppercase',
                size === 'sm' ? 'h-7 w-7 text-[10px]' : 'h-9 w-9 text-xs',
            )}
        >
            {actor.is_system ? <Bot className={size === 'sm' ? 'h-3.5 w-3.5' : 'h-4 w-4'} /> : actor.initials.slice(0, 2)}
        </span>
    );
}

interface SentencePart {
    text: string;
    strong?: boolean;
    muted?: boolean;
    /** Équipe de l'acteur, rendue en badge juste après son nom. */
    team?: boolean;
}

/**
 * La phrase d'une ligne, en morceaux (gras / atténué / badge d'équipe).
 * Tournures sans accord de genre : « a créé », jamais « s'est connecté(e) ».
 */
export function sentenceParts(entry: Pick<ActivityEntry, 'event' | 'actor' | 'subject'>, t: Translate): SentencePart[] {
    const actorParts: SentencePart[] = [{ text: entry.actor.name, strong: true }, ...(entry.actor.team ? [{ text: entry.actor.team, team: true }] : [])];
    const label: SentencePart = { text: subjectLabel(entry.subject), strong: true };
    const gone: SentencePart[] = entry.subject.deleted ? [{ text: ` ${t(NS, 'subject_deleted', '(supprimé)')}`, muted: true }] : [];

    switch (entry.event) {
        case 'login':
            return [...actorParts, { text: ' · ' }, { text: t(NS, 'sentence_login', 'Connexion au Manager') }];
        case 'logout':
            return [...actorParts, { text: ' · ' }, { text: t(NS, 'sentence_logout', 'Déconnexion') }];
        case 'login_failed':
            return [{ text: `${t(NS, 'sentence_login_failed', 'Échec de connexion sur le compte de')} ` }, label];
        case 'permissions_updated':
            return [...actorParts, { text: ` ${t(NS, 'verb_permissions_updated', 'a modifié les droits de')} ` }, label, ...gone];
        case 'exported':
            // Ce qui est exporté, c'est le journal lui-même : pas d'élément à nommer.
            return [...actorParts, { text: ` ${t(NS, 'verb_exported', "a exporté le journal d'activité")}` }];
        default: {
            const verbs: Record<'created' | 'updated' | 'deleted' | 'restored', string> = {
                created: t(NS, 'verb_created', 'a créé'),
                updated: t(NS, 'verb_updated', 'a modifié'),
                deleted: t(NS, 'verb_deleted', 'a supprimé'),
                restored: t(NS, 'verb_restored', 'a restauré'),
            };

            return [...actorParts, { text: ` ${verbs[entry.event]} ${entry.subject.type_phrase} ` }, label, ...gone];
        }
    }
}

/** La phrase en texte brut — description accessible du panneau de détail. */
export function sentenceText(entry: Pick<ActivityEntry, 'event' | 'actor' | 'subject'>, t: Translate): string {
    return sentenceParts(entry, t)
        .map((part) => (part.team ? ` (${part.text})` : part.text))
        .join('');
}

export function ActivitySentence({ entry, t, className }: { entry: Pick<ActivityEntry, 'event' | 'actor' | 'subject'>; t: Translate; className?: string }) {
    return (
        <span className={cn('text-foreground/90 break-words', className)}>
            {sentenceParts(entry, t).map((part, index) => (
                <Fragment key={index}>
                    {part.team ? (
                        <ActorTeamBadge team={part.text} t={t} className="ml-1" />
                    ) : part.strong ? (
                        <strong className="text-foreground font-semibold">{part.text}</strong>
                    ) : part.muted ? (
                        <span className="text-muted-foreground">{part.text}</span>
                    ) : (
                        part.text
                    )}
                </Fragment>
            ))}
        </span>
    );
}

const LEGEND_CHIP = 'px-1.5 py-0 text-[11px]';

/**
 * Légende des couleurs du flux — si la couleur porte un sens, on le dit. Elle
 * reprend les pastilles elles-mêmes, pas des pastilles de couleur : un ton pâle
 * réduit à un point ne se reconnaît plus.
 */
export function ActivityLegend({ t }: { t: Translate }) {
    const items: Array<{ event: ActivityEvent; label: string }> = [
        { event: 'created', label: t(NS, 'legend_created', 'Création') },
        { event: 'deleted', label: t(NS, 'legend_deleted', 'Suppression') },
        { event: 'permissions_updated', label: t(NS, 'legend_sensitive', 'Sensible : droits, échec de connexion') },
        { event: 'updated', label: t(NS, 'legend_other', 'Autres actions') },
    ];

    return (
        <ul className="flex flex-wrap items-center gap-1.5" aria-label={t(NS, 'legend_label', 'Légende des couleurs')}>
            {items.map((item) => (
                <li key={item.event}>
                    <span className={cn(CHIP_BASE, TONE_CHIP_CLASSES[eventTone(item.event)], LEGEND_CHIP)}>{item.label}</span>
                </li>
            ))}
        </ul>
    );
}

/** Légende des états de l'onglet Équipe : la pastille, puis ce qu'elle veut dire. */
export function TeamStateLegend({ t }: { t: Translate }) {
    const items: Array<{ state: ActivityTeamState; label: string }> = [
        { state: 'active', label: t(NS, 'legend_state_active', 'dernière action il y a moins de 24 h') },
        { state: 'quiet', label: t(NS, 'legend_state_quiet', 'entre 1 et 7 jours') },
        { state: 'inactive', label: t(NS, 'legend_state_inactive', 'plus de 7 jours sans action') },
        { state: 'never', label: t(NS, 'legend_state_never', 'aucune action ni connexion depuis le début du suivi') },
    ];

    return (
        <ul className="flex flex-wrap items-center gap-x-3 gap-y-1" aria-label={t(NS, 'legend_label', 'Légende des couleurs')}>
            {items.map((item) => (
                <li key={item.state} className="flex items-center gap-1.5">
                    <TeamStateChip state={item.state} t={t} />
                    <span>{item.label}</span>
                </li>
            ))}
        </ul>
    );
}
