"use client";

import Image from "next/image";
import { useEffect, useState } from "react";
import { MainTabBar } from "@/features/predictions/components/main-tab-bar";
import styles from "@/features/predictions/styles/predictions.module.css";
import historyStyles from "@/features/predictions/styles/history.module.css";
import { getApiUrl, PROJECT_CHANGED_EVENT } from "@/lib/auth";
import { getPredictionActivity } from "@/lib/predictions-client";
import type { PredictionActivity } from "@/types/predictions";

/* ---- helpers ---- */
function formatDate(value: string) {
  const date = new Date(value);
  return new Intl.DateTimeFormat("fr-FR", {
    dateStyle: "medium",
    timeStyle: "short",
  }).format(date);
}

function formatRelativeDate(value: string) {
  const date = new Date(value);
  const now = new Date();
  const diffMs = now.getTime() - date.getTime();
  const diffMinutes = Math.floor(diffMs / 60_000);
  const diffHours = Math.floor(diffMs / 3_600_000);
  const diffDays = Math.floor(diffMs / 86_400_000);

  if (diffMinutes < 1) return "À l'instant";
  if (diffMinutes < 60) return `Il y a ${diffMinutes} min`;
  if (diffHours < 24) return `Il y a ${diffHours}h`;
  if (diffDays === 1) return "Hier";
  if (diffDays < 7) return `Il y a ${diffDays} jours`;
  return formatDate(value);
}

function getDisplayName(user: NonNullable<PredictionActivity["user"]>) {
  return user.displayName ?? user.username;
}

function resolveProfileSrc(apiUrl: string, url: string | null | undefined): string | null {
  if (!url) return null;
  if (url.startsWith("http")) return url;
  return `${apiUrl}${url}`;
}

/**
 * Parse les valeurs encodées dans le message du serveur.
 * Format : "Nom a change CardTitle: Field1: val1 | Field2: val2"
 * Format création : "Nom a pronostique CardTitle" (pas de valeurs)
 */
function parseMessageFieldValues(message: string): Array<{ label: string; rawValue: string }> {
  // Cherche le séparateur entre le titre de la carte et les valeurs de champs
  // ex: "...Sexe du bebe: Sexe: fille" → après le premier ": " on a "Sexe: fille"
  const colonIdx = message.indexOf(": ");
  if (colonIdx === -1) return [];

  const valuesStr = message.slice(colonIdx + 2);
  // Évite de parser des messages sans valeurs structurées (pas de ": " interne)
  if (!valuesStr.includes(": ")) return [];

  return valuesStr
    .split(" | ")
    .map((part) => {
      const idx = part.indexOf(": ");
      if (idx === -1) return null;
      return { label: part.slice(0, idx), rawValue: part.slice(idx + 2) };
    })
    .filter((v): v is { label: string; rawValue: string } => v !== null && v.rawValue !== "(vide)" && v.rawValue.trim() !== "");
}

function isSexField(label: string): boolean {
  const l = label.toLowerCase();
  return l.includes("sexe") || l.includes("sex") || l.includes("genre");
}

function isWeightField(label: string): boolean {
  const l = label.toLowerCase();
  return l.includes("poid") || l.includes("weight");
}

function isNamesField(label: string): boolean {
  const l = label.toLowerCase();
  return l.includes("prenom") || l.includes("name");
}

function getMeasureUnit(label: string): string | null {
  const l = label.toLowerCase();
  if (l.includes("taille") || l.includes("height") || l.includes("périm") || l.includes("cranien") || l.includes("crânien")) return "cm";
  return null;
}

/* ---- Composant : valeur structurée depuis message parsé ---- */
function ParsedValueDisplay({ label, rawValue }: { label: string; rawValue: string }) {
  if (isWeightField(label)) {
    const num = parseFloat(rawValue);
    if (!isNaN(num)) {
      const kg = num >= 100 ? num / 1000 : num;
      return (
        <div className={historyStyles.valueRow}>
          <span className={historyStyles.fieldLabel}>{label}</span>
          <span className={styles.recapWeightBadge}>{kg.toFixed(3)}{"\u00A0"}kg</span>
        </div>
      );
    }
  }

  if (isSexField(label)) {
    const isGarcon = rawValue.toLowerCase().includes("gar") || rawValue.toLowerCase() === "garcon" || rawValue.toLowerCase() === "garçon";
    return (
      <div className={historyStyles.valueRow}>
        <span className={historyStyles.fieldLabel}>{label}</span>
        <div
          className={`${styles.recapSexAnswer} ${isGarcon ? styles.recapSexAnswerGarcon : styles.recapSexAnswerFille}`}
          style={{ padding: "0.3rem 0.65rem", display: "inline-flex" }}
        >
          <Image
            src={isGarcon ? "/images/pictos/choix-garcon.png" : "/images/pictos/choix-fille.png"}
            alt=""
            width={28}
            height={28}
            className={styles.recapSexIcon}
          />
          <span className={styles.recapSexLabel} style={{ fontSize: "0.95rem" }}>{rawValue}</span>
        </div>
      </div>
    );
  }

  if (isNamesField(label)) {
    const names = rawValue.split(/[,;]+/).map((n) => n.trim()).filter(Boolean);
    return (
      <div className={historyStyles.valueRow}>
        <span className={historyStyles.fieldLabel}>{label}</span>
        <div className={styles.recapParticipantNamesList}>
          {names.map((name) => (
            <span key={name} className={styles.recapParticipantNameChip}>{name}</span>
          ))}
        </div>
      </div>
    );
  }

  const num = parseFloat(rawValue);
  if (!isNaN(num) && rawValue.trim() !== "") {
    const unit = getMeasureUnit(label);
    return (
      <div className={historyStyles.valueRow}>
        <span className={historyStyles.fieldLabel}>{label}</span>
        <span className={historyStyles.valuePill}>{rawValue}{unit ? `\u00A0${unit}` : ""}</span>
      </div>
    );
  }

  return (
    <div className={historyStyles.valueRow}>
      <span className={historyStyles.fieldLabel}>{label}</span>
      <span className={historyStyles.valuePill}>{rawValue}</span>
    </div>
  );
}

/* ---- Composant : valeur structurée depuis entry.values (fallback) ---- */
type ActivityEntryValue = NonNullable<PredictionActivity["entry"]>["values"][number];

function EntryValueDisplay({ value }: { value: ActivityEntryValue }) {
  const label = value.field.label;

  if (isWeightField(label) && value.valueNumber != null) {
    const kg = value.valueNumber >= 100 ? value.valueNumber / 1000 : value.valueNumber;
    return (
      <div className={historyStyles.valueRow}>
        <span className={historyStyles.fieldLabel}>{label}</span>
        <span className={styles.recapWeightBadge}>{kg.toFixed(3)} kg</span>
      </div>
    );
  }

  if (isSexField(label) && value.valueText) {
    const isGarcon = value.valueText.toLowerCase().includes("gar");
    return (
      <div className={historyStyles.valueRow}>
        <span className={historyStyles.fieldLabel}>{label}</span>
        <div className={`${styles.recapSexAnswer} ${isGarcon ? styles.recapSexAnswerGarcon : styles.recapSexAnswerFille}`} style={{ padding: "0.3rem 0.65rem", display: "inline-flex" }}>
          <Image src={isGarcon ? "/images/pictos/choix-garcon.png" : "/images/pictos/choix-fille.png"} alt="" width={28} height={28} className={styles.recapSexIcon} />
          <span className={styles.recapSexLabel} style={{ fontSize: "0.95rem" }}>{value.valueText}</span>
        </div>
      </div>
    );
  }

  if (isNamesField(label) && value.valueText) {
    const names = value.valueText.split(/[,;]+/).map((n) => n.trim()).filter(Boolean);
    return (
      <div className={historyStyles.valueRow}>
        <span className={historyStyles.fieldLabel}>{label}</span>
        <div className={styles.recapParticipantNamesList}>
          {names.map((name) => <span key={name} className={styles.recapParticipantNameChip}>{name}</span>)}
        </div>
      </div>
    );
  }

  if (value.valueNumber != null) {
    const unit = getMeasureUnit(label);
    return (
      <div className={historyStyles.valueRow}>
        <span className={historyStyles.fieldLabel}>{label}</span>
        <span className={historyStyles.valuePill}>{value.valueNumber}{unit ? `\u00A0${unit}` : ""}</span>
      </div>
    );
  }

  if (value.valueText) {
    return (
      <div className={historyStyles.valueRow}>
        <span className={historyStyles.fieldLabel}>{label}</span>
        <span className={historyStyles.valuePill}>{value.valueText}</span>
      </div>
    );
  }

  return null;
}

type ActivityGlyphKind =
  | "prediction"
  | "update"
  | "score"
  | "validated"
  | "lock"
  | "unlock"
  | "target"
  | "card"
  | "trash"
  | "log";

function getActivityGlyphKind(type: string): ActivityGlyphKind {
  switch (type) {
    case "PREDICTION_CREATED": return "prediction";
    case "PREDICTION_UPDATED": return "update";
    case "SCORE_SUGGESTED": return "score";
    case "SCORE_VALIDATED": return "validated";
    case "GAME_CLOSED": return "lock";
    case "GAME_OPENED": return "unlock";
    case "OUTCOME_SET": return "target";
    case "CARD_CREATED":
    case "CARD_UPDATED": return "card";
    case "CARD_DELETED": return "trash";
    default: return "log";
  }
}

function ActivityGlyph({ kind }: Readonly<{ kind: ActivityGlyphKind }>) {
  const commonProps = {
    fill: "none",
    stroke: "currentColor",
    strokeWidth: 1.9,
    strokeLinecap: "round" as const,
    strokeLinejoin: "round" as const,
    viewBox: "0 0 24 24",
    ariaHidden: true,
  };

  switch (kind) {
    case "prediction":
      return (
        <svg viewBox={commonProps.viewBox} fill={commonProps.fill} stroke={commonProps.stroke} strokeWidth={commonProps.strokeWidth} strokeLinecap={commonProps.strokeLinecap} strokeLinejoin={commonProps.strokeLinejoin} aria-hidden>
          <path d="M4 20l4.3-1.1L18.6 8.6a2.2 2.2 0 0 0-3.1-3.1L5.2 15.8 4 20Z" />
          <path d="m13.8 7.2 3 3" />
        </svg>
      );
    case "update":
      return (
        <svg viewBox={commonProps.viewBox} fill={commonProps.fill} stroke={commonProps.stroke} strokeWidth={commonProps.strokeWidth} strokeLinecap={commonProps.strokeLinecap} strokeLinejoin={commonProps.strokeLinejoin} aria-hidden>
          <path d="M19 8a7 7 0 0 0-11.8-2L5 8" />
          <path d="M5 4v4h4" />
          <path d="M5 16a7 7 0 0 0 11.8 2L19 16" />
          <path d="M19 20v-4h-4" />
        </svg>
      );
    case "score":
      return (
        <svg viewBox={commonProps.viewBox} fill={commonProps.fill} stroke={commonProps.stroke} strokeWidth={commonProps.strokeWidth} strokeLinecap={commonProps.strokeLinecap} strokeLinejoin={commonProps.strokeLinejoin} aria-hidden>
          <path d="m12 3 2.5 5.1 5.6.8-4 3.9.9 5.5L12 15.8 7 18.3l.9-5.5-4-3.9 5.6-.8Z" />
        </svg>
      );
    case "validated":
      return (
        <svg viewBox={commonProps.viewBox} fill={commonProps.fill} stroke={commonProps.stroke} strokeWidth={commonProps.strokeWidth} strokeLinecap={commonProps.strokeLinecap} strokeLinejoin={commonProps.strokeLinejoin} aria-hidden>
          <circle cx="12" cy="10" r="5.5" />
          <path d="m9.8 10.2 1.5 1.6 3-3.2" />
          <path d="M10.2 15.2 8.8 20l3.2-1.9L15.2 20l-1.4-4.8" />
        </svg>
      );
    case "lock":
      return (
        <svg viewBox={commonProps.viewBox} fill={commonProps.fill} stroke={commonProps.stroke} strokeWidth={commonProps.strokeWidth} strokeLinecap={commonProps.strokeLinecap} strokeLinejoin={commonProps.strokeLinejoin} aria-hidden>
          <rect x="5" y="11" width="14" height="9" rx="2.5" />
          <path d="M8 11V8.5a4 4 0 1 1 8 0V11" />
        </svg>
      );
    case "unlock":
      return (
        <svg viewBox={commonProps.viewBox} fill={commonProps.fill} stroke={commonProps.stroke} strokeWidth={commonProps.strokeWidth} strokeLinecap={commonProps.strokeLinecap} strokeLinejoin={commonProps.strokeLinejoin} aria-hidden>
          <rect x="5" y="11" width="14" height="9" rx="2.5" />
          <path d="M16 11V8.5a4 4 0 0 0-7.7-1.4" />
        </svg>
      );
    case "target":
      return (
        <svg viewBox={commonProps.viewBox} fill={commonProps.fill} stroke={commonProps.stroke} strokeWidth={commonProps.strokeWidth} strokeLinecap={commonProps.strokeLinecap} strokeLinejoin={commonProps.strokeLinejoin} aria-hidden>
          <circle cx="12" cy="12" r="7" />
          <circle cx="12" cy="12" r="3" />
          <path d="M12 2v3" />
          <path d="M22 12h-3" />
          <path d="M12 22v-3" />
          <path d="M2 12h3" />
        </svg>
      );
    case "card":
      return (
        <svg viewBox={commonProps.viewBox} fill={commonProps.fill} stroke={commonProps.stroke} strokeWidth={commonProps.strokeWidth} strokeLinecap={commonProps.strokeLinecap} strokeLinejoin={commonProps.strokeLinejoin} aria-hidden>
          <rect x="4" y="6" width="12" height="14" rx="2.5" />
          <path d="M8 10h4" />
          <path d="M8 14h6" />
          <path d="M16 9h2.5a1.5 1.5 0 0 1 1.5 1.5V17" />
        </svg>
      );
    case "trash":
      return (
        <svg viewBox={commonProps.viewBox} fill={commonProps.fill} stroke={commonProps.stroke} strokeWidth={commonProps.strokeWidth} strokeLinecap={commonProps.strokeLinecap} strokeLinejoin={commonProps.strokeLinejoin} aria-hidden>
          <path d="M4 7h16" />
          <path d="M9 4h6" />
          <path d="m6 7 1 12h10l1-12" />
          <path d="M10 11v5" />
          <path d="M14 11v5" />
        </svg>
      );
    default:
      return (
        <svg viewBox={commonProps.viewBox} fill={commonProps.fill} stroke={commonProps.stroke} strokeWidth={commonProps.strokeWidth} strokeLinecap={commonProps.strokeLinecap} strokeLinejoin={commonProps.strokeLinejoin} aria-hidden>
          <path d="M7 7h10" />
          <path d="M7 12h10" />
          <path d="M7 17h6" />
        </svg>
      );
  }
}

function getActivityBadgeClass(type: string): string {
  if (type === "GAME_CLOSED" || type === "GAME_OPENED") return historyStyles.badgeSystem;
  if (type === "SCORE_VALIDATED") return historyStyles.badgeSuccess;
  if (type === "SCORE_SUGGESTED") return historyStyles.badgeWarning;
  if (type === "PREDICTION_CREATED" || type === "PREDICTION_UPDATED") return historyStyles.badgePrimary;
  return historyStyles.badgeMuted;
}

function UserAvatar({ user, apiUrl }: { user: NonNullable<PredictionActivity["user"]>; apiUrl: string }) {
  const name = getDisplayName(user);
  const initials = name
    .split(/\s+/)
    .filter(Boolean)
    .slice(0, 2)
    .map((p) => p[0]?.toUpperCase() ?? "")
    .join("") || "?";
  const imageSrc = resolveProfileSrc(apiUrl, user.profileImageUrl);

  return (
    <div
      className={`${styles.recapAvatar} ${styles.recapAvatarSm}`}
      style={user.profileBgColor ? { background: user.profileBgColor } : undefined}
      aria-hidden="true"
    >
      {imageSrc ? <img src={imageSrc} alt="" /> : <span>{initials}</span>}
    </div>
  );
}

export default function PredictionsHistoryPage() {
  const apiUrl = getApiUrl();
  const [activity, setActivity] = useState<PredictionActivity[]>([]);
  const [loading, setLoading] = useState(true);
  const [message, setMessage] = useState("");
  const [projectRefreshKey, setProjectRefreshKey] = useState(0);

  useEffect(() => {
    const onProjectChanged = () => {
      setProjectRefreshKey((current) => current + 1);
    };
    window.addEventListener(PROJECT_CHANGED_EVENT, onProjectChanged);
    return () => window.removeEventListener(PROJECT_CHANGED_EVENT, onProjectChanged);
  }, []);

  useEffect(() => {
    setLoading(true);
    setMessage("");
    getPredictionActivity()
      .then((payload) => setActivity(payload))
      .catch((error) => setMessage(error instanceof Error ? error.message : "Impossible de charger l'historique"))
      .finally(() => setLoading(false));
  }, [projectRefreshKey]);

  return (
    <>
      <section className={`${styles.recapHero} ${styles.historyHero}`}>
        <div className={styles.recapHeroContent}>
          <span className={styles.recapHeroEyebrow}>Activité</span>
          <h1>Historique des actions</h1>
          <p>Toutes les modifications du projet, en temps réel.</p>
          <div className={styles.recapHeroStats}>
            <div className={styles.recapHeroStatChip}>
              <span className={`${styles.recapHeroStatValue} ${historyStyles.heroStatIcon}`}>
                <ActivityGlyph kind="prediction" />
              </span>
              <span className={styles.recapHeroStatLabel}>Pronostics</span>
            </div>
            <div className={styles.recapHeroStatChip}>
              <span className={`${styles.recapHeroStatValue} ${historyStyles.heroStatIcon}`}>
                <ActivityGlyph kind="update" />
              </span>
              <span className={styles.recapHeroStatLabel}>Modifs</span>
            </div>
            {/* <div className={styles.recapHeroStatChip}>
              <span className={styles.recapHeroStatValue}>⭐</span>
              <span className={styles.recapHeroStatLabel}>Scores</span>
            </div> */}
          </div>
        </div>
        <div className={styles.historyHeroIllustration} aria-hidden="true">
          <span className={styles.historyHeroLine} />
          <span className={styles.historyHeroDot1} />
          <span className={styles.historyHeroDot2} />
          <span className={styles.historyHeroDot3} />
        </div>
      </section>

      <MainTabBar />

      {!loading && !message && activity.length > 0 && (
        <div className={styles.recapSectionHeading} style={{ padding: "0 0.5rem" }}>
          <p>{activity.length} événement{activity.length !== 1 ? "s" : ""} enregistré{activity.length !== 1 ? "s" : ""}.</p>
        </div>
      )}

      {loading && (
        <div className={styles.loadingScreen}>
          <p>Chargement de l'historique…</p>
        </div>
      )}

      {!loading && message && (
        <p className={historyStyles.errorMsg}>{message}</p>
      )}

      {!loading && !message && activity.length === 0 && (
        <p className={styles.empty} style={{ margin: "0 0.5rem" }}>Aucun événement pour le moment.</p>
      )}

      {!loading && !message && activity.length > 0 && (
        <div className={historyStyles.timelineList}>
          {activity.map((item) => {
            // Priorité : parser les valeurs depuis le message (format serveur fiable)
            const parsedValues = parseMessageFieldValues(item.message);
            // Fallback : entry.values (état courant de l'entrée, peut différer)
            const fallbackValues = parsedValues.length === 0 ? (item.entry?.values ?? []) : [];
            const hasDisplayValues = parsedValues.length > 0 || fallbackValues.length > 0;

            // Extraire le nom de l'auteur depuis le message si item.user est null
            // Ex: "Valerie a change X: ..." → "Valerie"
            const authorFromMessage = !item.user
              ? item.message.split(/\s+a\s+(change|pronostique|cree|fixe|suggere|valide)/i)?.[0] ?? null
              : null;
            const activityGlyphKind = getActivityGlyphKind(item.type);

            return (
              <article key={item.id} className={historyStyles.timelineCard}>
                {/* Left: avatar ou icône système */}
                <div className={historyStyles.timelineAvatarCol}>
                  {item.user ? (
                    <UserAvatar user={item.user} apiUrl={apiUrl} />
                  ) : (
                    <div className={historyStyles.systemIcon} aria-hidden="true">
                      <span className={historyStyles.systemIconGlyph}>
                        <ActivityGlyph kind={activityGlyphKind} />
                      </span>
                    </div>
                  )}
                  <div className={historyStyles.timelineLine} aria-hidden="true" />
                </div>

                {/* Right: contenu */}
                <div className={historyStyles.timelineContent}>
                  <div className={historyStyles.timelineHeader}>
                    <div className={historyStyles.timelineHeadLeft}>
                      {(item.user || authorFromMessage) && (
                        <strong className={historyStyles.userName}>
                          {item.user ? getDisplayName(item.user) : authorFromMessage}
                        </strong>
                      )}
                      <span className={`${historyStyles.activityLabel} ${getActivityBadgeClass(item.type)}`}>
                        <span className={historyStyles.activityLabelIcon} aria-hidden="true">
                          <ActivityGlyph kind={activityGlyphKind} />
                        </span>
                        <span className={historyStyles.activityLabelText}>{item.card?.title ?? item.message}</span>
                      </span>
                    </div>
                    <time className={historyStyles.timelineTime} dateTime={item.createdAt} title={formatDate(item.createdAt)}>
                      {formatRelativeDate(item.createdAt)}
                    </time>
                  </div>

                  {hasDisplayValues && (
                    <div className={historyStyles.valuesBlock}>
                      {parsedValues.map((v) => (
                        <ParsedValueDisplay key={v.label} label={v.label} rawValue={v.rawValue} />
                      ))}
                      {fallbackValues.map((v) => (
                        <EntryValueDisplay key={v.fieldId} value={v} />
                      ))}
                    </div>
                  )}
                </div>
              </article>
            );
          })}
        </div>
      )}
    </>
  );
}
