"use client";

// Mail data layer. A dedicated Mail reader over the be-crm data door (crm.mail.*), distinct from
// the Messenger chat and from the work-item Inbox. Live via the AppShell SDK; a small mock keeps the
// demo working before the Shell + be-crm are connected.
//
// Live contract (be-crm):
//   query crm.mail.list      {}                          -> MailThread[]
//   query crm.mail.history   { threadId }                -> MailMessage[]
//   cmd   crm.mail.reply     { threadId, content }       -> { interactionId, threadId }
//   cmd   crm.mail.internal  { recipientUserId, subject?, text?, html? } -> { threadId }
//   cmd   crm.mail.send      { target, subject?, text?, html?, mirrorToUserId? } -> { commandId }
//   query crm.messenger.directory { kind, limit }        -> people to compose to (reused)

import { useCallback, useMemo, useState } from "react";
import { useAppShell, useQuery } from "@abe-kap/appshell-sdk/react";
import { isShellConfigured } from "./appshell";

export interface MailThread {
  threadId: string; subject: string | null; participants: string[]; unread: number; lastMessage?: string; lastAt?: string;
}
export interface MailMessage {
  interactionId: string; actorId: string | null; kind: string; occurredAt: string; html: string | null; text: string | null;
}
export interface MailPerson { id: string; name: string; kind: "staff" | "customer" }

const SHELL = isShellConfigured();

/* ============================ Thread list ============================ */

export interface MailListData {
  live: boolean; loading: boolean; error: string | null; threads: MailThread[]; refetch: () => void;
}

export function useMailThreads(): MailListData {
  if (SHELL) {
    const q = useQuery<MailThread[]>("crm.mail.list", {});
    return { live: true, loading: q.loading, error: q.error?.message ?? null, threads: q.data ?? [], refetch: q.refetch };
  }
  return { live: false, loading: false, error: null, threads: MOCK_THREADS, refetch: () => {} };
}

/* ============================ One thread ============================ */

export interface MailThreadData {
  loading: boolean; error: string | null; messages: MailMessage[]; reply: (content: string) => Promise<void>; refetch: () => void;
}

export function useMailThread(threadId: string | null): MailThreadData {
  if (SHELL) return useLiveThread(threadId);
  return useMockThread(threadId);
}

function useLiveThread(threadId: string | null): MailThreadData {
  const { sdk } = useAppShell();
  const q = useQuery<MailMessage[]>("crm.mail.history", threadId ? { threadId } : { threadId: "" });
  const reply = useCallback(async (content: string) => {
    if (!threadId) return;
    await sdk.command("crm.mail.reply", { threadId, content });
    q.refetch();
  }, [sdk, threadId, q]);
  return { loading: q.loading, error: q.error?.message ?? null, messages: threadId ? (q.data ?? []) : [], reply, refetch: q.refetch };
}

/* ============================ Compose ============================ */

export interface ComposeData {
  directory: MailPerson[];
  sendInternal: (recipientUserId: string, subject: string, text: string) => Promise<void>;
  sendExternal: (target: string, subject: string, text: string, mirrorToUserId?: string) => Promise<void>;
}

export function useMailCompose(onSent: () => void): ComposeData {
  if (SHELL) {
    const { sdk } = useAppShell();
    const dirQ = useQuery<MailPerson[]>("crm.messenger.directory", { kind: "all", limit: 100 });
    const directory = useMemo(() => (dirQ.data ?? []).map((d) => ({ id: (d as unknown as { id: string }).id, name: (d as unknown as { displayName?: string; name?: string }).displayName ?? (d as unknown as { name?: string }).name ?? "", kind: (d as MailPerson).kind })), [dirQ.data]);
    const sendInternal = useCallback(async (recipientUserId: string, subject: string, text: string) => {
      await sdk.command("crm.mail.internal", { recipientUserId, subject, text, html: `<p>${escapeHtml(text)}</p>` });
      onSent();
    }, [sdk, onSent]);
    const sendExternal = useCallback(async (target: string, subject: string, text: string, mirrorToUserId?: string) => {
      await sdk.command("crm.mail.send", { target, subject, text, html: `<p>${escapeHtml(text)}</p>`, ...(mirrorToUserId ? { mirrorToUserId } : {}) });
      onSent();
    }, [sdk, onSent]);
    return { directory, sendInternal, sendExternal };
  }
  return { directory: MOCK_PEOPLE, sendInternal: async () => onSent(), sendExternal: async () => onSent() };
}

function escapeHtml(s: string): string {
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}

/* ============================ Mock (demo mode) ============================ */

const now = () => new Date().toISOString();
const MOCK_PEOPLE: MailPerson[] = [
  { id: "pp_sofia", name: "Sofia Ramirez", kind: "staff" },
  { id: "cust_acme", name: "Acme Roofing (Client)", kind: "customer" },
];
const MOCK_THREADS: MailThread[] = [
  { threadId: "mt_1", subject: "Welcome to the Founders Club", participants: ["you", "system"], unread: 1, lastMessage: "Thanks for joining…", lastAt: now() },
  { threadId: "mt_2", subject: "Storm response — East side", participants: ["you", "pp_sofia"], unread: 0, lastMessage: "Crew rolling out at 7", lastAt: now() },
];
function useMockThread(threadId: string | null): MailThreadData {
  const [extra, setExtra] = useState<MailMessage[]>([]);
  const base: MailMessage[] = threadId === "mt_1"
    ? [{ interactionId: "m1", actorId: "system", kind: "EMAIL", occurredAt: now(), html: "<p>Thanks for joining the <b>Founders Club</b>. Set up your account to get started.</p>", text: "Thanks for joining the Founders Club." }]
    : threadId === "mt_2"
      ? [{ interactionId: "m2", actorId: "pp_sofia", kind: "EMAIL", occurredAt: now(), html: "<p>Crew is rolling out at 7. Confirm the Henderson scope?</p>", text: "Crew rolling out at 7." }]
      : [];
  const reply = useCallback(async (content: string) => {
    setExtra((l) => [...l, { interactionId: `r_${l.length}`, actorId: "you", kind: "MESSAGE", occurredAt: now(), html: null, text: content }]);
  }, []);
  return { loading: false, error: null, messages: threadId ? [...base, ...extra] : [], reply, refetch: () => {} };
}
