"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import {
  upsertDemoConversation,
  useDemoBrowserState,
} from "@/lib/demo-session-store";
import type {
  CoachMessageSource,
  DemoCoachConversationRecord,
} from "@/lib/types";

type CoachReplyResponse = {
  assistantMessage: {
    id: string;
    conversationId: string;
    role: "assistant";
    content: string;
    createdAt: string;
    sources: CoachMessageSource[];
  };
};

async function readJson<T>(response: Response) {
  const payload = (await response.json()) as T | { error?: string };

  if (!response.ok) {
    const errorPayload = payload as { error?: string };
    throw new Error(errorPayload.error ?? "La requete a echoue.");
  }

  return payload as T;
}

function formatConversationDate(value: string | null) {
  if (!value) {
    return "Aucune activite";
  }

  return new Intl.DateTimeFormat("fr-FR", {
    day: "2-digit",
    month: "short",
    hour: "2-digit",
    minute: "2-digit",
  }).format(new Date(value));
}

function formatMessageTime(value: string) {
  return new Intl.DateTimeFormat("fr-FR", {
    hour: "2-digit",
    minute: "2-digit",
  }).format(new Date(value));
}

function normalizeWhitespace(value: string) {
  return value.replace(/\s+/g, " ").trim();
}

function createConversationTitle(seed?: string) {
  const normalized = normalizeWhitespace(seed ?? "");
  return normalized.length > 0
    ? normalized.slice(0, 96).trimEnd()
    : "Nouvelle conversation";
}

function createConversationRecord(seed?: string): DemoCoachConversationRecord {
  const now = new Date().toISOString();

  return {
    id: crypto.randomUUID(),
    title: createConversationTitle(seed),
    messageCount: 0,
    createdAt: now,
    updatedAt: now,
    lastMessageAt: null,
    messages: [],
  };
}

function SourcePill({ source }: { source: CoachMessageSource }) {
  const colorClass =
    source.kind === "knowledge"
      ? "bg-[rgba(23,117,186,0.08)] text-[var(--primary)]"
      : source.kind === "report"
        ? "bg-[rgba(193,22,27,0.08)] text-[var(--accent-red)]"
        : source.kind === "profile"
          ? "bg-[rgba(216,142,4,0.14)] text-[var(--accent-gold)]"
          : "bg-[var(--surface-soft)] text-[var(--foreground)]";

  return (
    <div className="rounded-[18px] border border-[var(--line)] bg-[var(--surface-soft)] px-3 py-2">
      <div className="flex flex-wrap items-center gap-2">
        <span
          className={`rounded-full px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.16em] ${colorClass}`}
        >
          {source.label}
        </span>
        {typeof source.similarity === "number" ? (
          <span className="text-[10px] font-semibold uppercase tracking-[0.16em] text-[var(--foreground)]">
            {(source.similarity * 100).toFixed(0)}%
          </span>
        ) : null}
      </div>
      <p className="mt-2 text-xs leading-6 text-[var(--foreground)]">
        {source.detail}
      </p>
    </div>
  );
}

export function CoachShell() {
  const messagesEndRef = useRef<HTMLDivElement | null>(null);
  const browserState = useDemoBrowserState();
  const [selectedConversationId, setSelectedConversationId] = useState<string | null>(
    null,
  );
  const [draft, setDraft] = useState("");
  const [bootstrapping, setBootstrapping] = useState(true);
  const [pending, setPending] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const conversations = browserState.conversations;
  const selectedConversation = useMemo(
    () =>
      conversations.find((conversation) => conversation.id === selectedConversationId) ??
      null,
    [conversations, selectedConversationId],
  );
  const messages = useMemo(
    () => selectedConversation?.messages ?? [],
    [selectedConversation],
  );

  useEffect(() => {
    setSelectedConversationId((current) => current ?? conversations[0]?.id ?? null);
    setBootstrapping(false);
  }, [conversations]);

  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages, pending]);

  function handleNewConversation() {
    if (pending) {
      return;
    }

    const nextConversation = createConversationRecord();
    upsertDemoConversation(nextConversation);
    setSelectedConversationId(nextConversation.id);
    setError(null);
  }

  async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();

    const content = draft.trim();

    if (!content || pending) {
      return;
    }

    setPending(true);
    setError(null);

    const previousDraft = draft;
    setDraft("");

    try {
      const conversation =
        selectedConversation ?? createConversationRecord(content);

      if (!selectedConversation) {
        upsertDemoConversation(conversation);
        setSelectedConversationId(conversation.id);
      }

      const response = await fetch("/api/coach/reply", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          conversationId: conversation.id,
          history: conversation.messages,
          userMessage: content,
          onboardingPromptContext: browserState.onboarding.promptContext,
          actionPlanPrompt: browserState.onboarding.actionPlanPrompt,
          recentSessions: browserState.sessions.slice(0, 5).map((session) => ({
            scenarioTitle: session.scenarioSnapshot.title,
            scenarioTargetSkill: session.scenarioSnapshot.targetSkill,
            status: session.status,
            updatedAt: session.updatedAt,
            finalAssessment: session.finalAssessment
              ? {
                  summary: session.finalAssessment.summary,
                  readiness: session.finalAssessment.readiness,
                  actionPlan: session.finalAssessment.actionPlan,
                }
              : null,
          })),
        }),
      });

      const payload = await readJson<CoachReplyResponse>(response);
      const now = new Date().toISOString();
      const userMessage = {
        id: crypto.randomUUID(),
        conversationId: conversation.id,
        role: "user" as const,
        content,
        createdAt: now,
        sources: [],
      };

      const assistantMessage = payload.assistantMessage;
      const nextConversation: DemoCoachConversationRecord = {
        ...conversation,
        title:
          conversation.messageCount === 0
            ? createConversationTitle(content)
            : conversation.title,
        messageCount: conversation.messageCount + 2,
        updatedAt: assistantMessage.createdAt,
        lastMessageAt: assistantMessage.createdAt,
        messages: [...conversation.messages, userMessage, assistantMessage],
      };

      upsertDemoConversation(nextConversation);
      setSelectedConversationId(nextConversation.id);
    } catch (caughtError) {
      setDraft(previousDraft);
      setError(
        caughtError instanceof Error
          ? caughtError.message
          : "Le coach n'a pas pu repondre.",
      );
    } finally {
      setPending(false);
    }
  }

  if (bootstrapping) {
    return (
      <section className="glass-card fade-in-up mt-4 rounded-[32px] p-8 text-center">
        <p className="text-sm font-semibold uppercase tracking-[0.22em] text-[var(--primary)]">
          Coach
        </p>
        <h2 className="mt-3 text-3xl font-extrabold tracking-[-0.04em] text-[var(--ink)]">
          Initialisation du coach...
        </h2>
      </section>
    );
  }

  return (
    <section
      data-tutorial-target="coach-shell"
      className="glass-card fade-in-up mt-4 overflow-hidden rounded-[32px]"
    >
      <div className="grid min-h-[720px] gap-0 xl:grid-cols-[320px_minmax(0,1fr)]">
        <aside className="border-b border-[var(--line)] bg-[var(--surface-soft)]/55 p-4 xl:border-r xl:border-b-0">
          <div className="rounded-[26px] border border-[var(--line)] bg-white p-4">
            <p className="text-[11px] font-semibold uppercase tracking-[0.22em] text-[var(--accent-gold)]">
              Coach
            </p>
            <h2 className="mt-2 text-2xl font-extrabold tracking-[-0.04em] text-[var(--ink)]">
              Conversations
            </h2>
            <p className="mt-2 text-sm leading-7 text-[var(--foreground)]">
              Reponses ancrees dans votre profil, vos simulations et la base
              coach YAML de la demo.
            </p>
            <button
              type="button"
              onClick={handleNewConversation}
              className="mt-4 inline-flex w-full items-center justify-center rounded-full bg-[var(--primary)] px-4 py-3 text-sm font-semibold text-white transition-colors hover:bg-[var(--primary-strong)]"
            >
              Nouvelle conversation
            </button>
          </div>

          <div className="mt-4 max-h-[520px] space-y-2 overflow-y-auto pr-1">
            {conversations.length > 0 ? (
              conversations.map((conversation) => {
                const active = conversation.id === selectedConversationId;

                return (
                  <button
                    key={conversation.id}
                    type="button"
                    onClick={() => setSelectedConversationId(conversation.id)}
                    className={`w-full rounded-[22px] border px-4 py-4 text-left transition ${
                      active
                        ? "border-[rgba(23,117,186,0.22)] bg-[rgba(23,117,186,0.08)]"
                        : "border-[var(--line)] bg-white hover:border-[var(--primary)]"
                    }`}
                  >
                    <p className="text-sm font-semibold text-[var(--ink)]">
                      {conversation.title}
                    </p>
                    <p className="mt-2 text-xs uppercase tracking-[0.16em] text-[var(--foreground)]">
                      {conversation.messageCount} message
                      {conversation.messageCount > 1 ? "s" : ""}
                    </p>
                    <p className="mt-2 text-xs text-[var(--foreground)]">
                      {formatConversationDate(
                        conversation.lastMessageAt ?? conversation.updatedAt,
                      )}
                    </p>
                  </button>
                );
              })
            ) : (
              <div className="rounded-[22px] border border-dashed border-[var(--line)] bg-white px-4 py-6 text-center">
                <p className="text-sm font-semibold text-[var(--ink)]">
                  Aucune conversation pour le moment.
                </p>
                <p className="mt-2 text-sm leading-7 text-[var(--foreground)]">
                  Lancez un premier echange pour ouvrir votre espace coach.
                </p>
              </div>
            )}
          </div>
        </aside>

        <div className="flex min-h-[720px] flex-col">
          <header className="border-b border-[var(--line)] px-5 py-5 sm:px-7">
            <p className="text-sm font-semibold uppercase tracking-[0.2em] text-[var(--accent-red)]">
              Mode coach
            </p>
            <div className="mt-2 flex flex-col gap-3 lg:flex-row lg:items-end lg:justify-between">
              <div>
                <h2 className="text-3xl font-extrabold tracking-[-0.04em] text-[var(--ink)]">
                  {selectedConversation?.title ?? "Nouvelle conversation"}
                </h2>
                <p className="mt-2 max-w-3xl text-sm leading-7 text-[var(--foreground)]">
                  Le coach croise votre contexte, vos rapports de simulation et la
                  base documentaire locale. En cas de source insuffisante, il le
                  signale explicitement.
                </p>
              </div>
              {selectedConversation ? (
                <div className="rounded-full bg-[var(--surface-soft)] px-4 py-2 text-xs font-semibold uppercase tracking-[0.16em] text-[var(--foreground)]">
                  {selectedConversation.messageCount} message
                  {selectedConversation.messageCount > 1 ? "s" : ""}
                </div>
              ) : null}
            </div>
          </header>

          <div className="flex-1 overflow-y-auto px-5 py-6 sm:px-7">
            {messages.length > 0 ? (
              <div className="space-y-5">
                {messages.map((message) => {
                  const isAssistant = message.role === "assistant";

                  return (
                    <article
                      key={message.id}
                      className={`flex ${isAssistant ? "justify-start" : "justify-end"}`}
                    >
                      <div
                        className={`max-w-[92%] rounded-[28px] px-5 py-4 shadow-[0_10px_30px_rgba(35,52,61,0.05)] sm:max-w-[80%] ${
                          isAssistant
                            ? "border border-[var(--line)] bg-white text-[var(--ink)]"
                            : "bg-[var(--primary)] text-white"
                        }`}
                      >
                        <div className="flex flex-wrap items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.18em] opacity-80">
                          <span>{isAssistant ? "Coach" : "Vous"}</span>
                          <span>&bull;</span>
                          <span>{formatMessageTime(message.createdAt)}</span>
                        </div>
                        <p className="mt-3 whitespace-pre-wrap text-sm leading-7">
                          {message.content}
                        </p>

                        {isAssistant && message.sources.length > 0 ? (
                          <div className="mt-4 border-t border-[var(--line)] pt-4">
                            <p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-[var(--accent-gold)]">
                              Sources mobilisees
                            </p>
                            <div className="mt-3 space-y-2.5">
                              {message.sources.map((source) => (
                                <SourcePill key={source.id} source={source} />
                              ))}
                            </div>
                          </div>
                        ) : null}
                      </div>
                    </article>
                  );
                })}

                {pending ? (
                  <div className="flex justify-start">
                    <div className="rounded-[28px] border border-[var(--line)] bg-white px-5 py-4 shadow-[0_10px_30px_rgba(35,52,61,0.05)]">
                      <div className="flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-[var(--foreground)]">
                        <span>Coach</span>
                        <span>&bull;</span>
                        <span>analyse en cours</span>
                      </div>
                      <div className="mt-4 flex items-center gap-2 text-[var(--primary)]">
                        <span className="pulse-dot h-2.5 w-2.5 rounded-full bg-current [animation-delay:0ms]" />
                        <span className="pulse-dot h-2.5 w-2.5 rounded-full bg-current [animation-delay:150ms]" />
                        <span className="pulse-dot h-2.5 w-2.5 rounded-full bg-current [animation-delay:300ms]" />
                      </div>
                    </div>
                  </div>
                ) : null}

                <div ref={messagesEndRef} />
              </div>
            ) : (
              <div className="flex h-full items-center justify-center">
                <div className="max-w-2xl rounded-[28px] border border-dashed border-[var(--line)] bg-[var(--surface-soft)] px-8 py-10 text-center">
                  <p className="text-sm font-semibold uppercase tracking-[0.22em] text-[var(--primary)]">
                    Coach disponible
                  </p>
                  <h3 className="mt-3 text-3xl font-extrabold tracking-[-0.04em] text-[var(--ink)]">
                    Posez une question sur votre pratique manageriale.
                  </h3>
                  <p className="mt-4 text-sm leading-8 text-[var(--foreground)]">
                    Exemple : Aidez-moi a preparer un entretien difficile avec
                    une equipe en transformation. Ou bien : Que retenir de mes
                    derniers rapports pour mon prochain point d&apos;equipe ?
                  </p>
                </div>
              </div>
            )}
          </div>

          <div
            data-tutorial-target="coach-composer"
            className="border-t border-[var(--line)] px-5 py-5 sm:px-7"
          >
            {error ? (
              <div className="mb-4 rounded-[22px] border border-[rgba(159,25,24,0.16)] bg-[rgba(159,25,24,0.06)] px-4 py-3 text-sm leading-7 text-[var(--accent-red)]">
                {error}
              </div>
            ) : null}

            <form onSubmit={handleSubmit} className="flex flex-col gap-4">
              <textarea
                rows={4}
                value={draft}
                onChange={(event) => setDraft(event.target.value)}
                disabled={pending}
                placeholder="Decrivez votre situation, votre question ou le type d'aide attendu..."
                className="min-h-32 rounded-[28px] border border-[var(--line)] bg-white px-5 py-4 text-sm leading-7 text-[var(--ink)] outline-none transition-colors placeholder:text-[var(--foreground)]/70 focus:border-[var(--primary)] disabled:cursor-not-allowed disabled:opacity-60"
              />
              <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                <p className="text-sm text-[var(--foreground)]">
                  Le coach cite ses appuis documentaires sous chaque reponse.
                </p>
                <button
                  type="submit"
                  disabled={pending || !draft.trim()}
                  className="inline-flex items-center justify-center rounded-full bg-[var(--primary)] px-6 py-3 text-sm font-semibold text-white transition-colors hover:bg-[var(--primary-strong)] disabled:cursor-not-allowed disabled:opacity-60"
                >
                  Envoyer au coach
                </button>
              </div>
            </form>
          </div>
        </div>
      </div>
    </section>
  );
}
