/**
 * CRM 名單：以搜尋／篩選／分頁的工作清單取代會重複 Contact 的八欄看板。
 * 階段仍保留完整能力，選中 Contact 後在右側詳情操作。
 */
import { useCallback, useEffect, useMemo, useState, type FormEvent } from "react";
import { Link, useSearchParams } from "react-router-dom";
import { PageHeader } from "../components/layout/PageHeader";
import { Badge, Button, EmptyState, Input, Pager, Select, Textarea } from "../components/ui";
import { useRepos } from "../data/DataContext";
import type { Contact, ContactDetail, ContactStage } from "../domain/types";
import { useI18n } from "../i18n/I18nContext";
import { useFormatApiError } from "../lib/apiErrors";
import { formatTimeAgo } from "../lib/time";
import "../styles/radar.css";

const PAGE_SIZE = 20;

const STAGES: ContactStage[] = [
  "new_found",
  "engaged",
  "dm_sent",
  "replied",
  "quoted",
  "won",
  "lost",
];

type StageFilter = "" | "needs_follow_up" | ContactStage;
type SortMode = "last_touch_at" | "intent_score";

export function CrmBoardPage() {
  const { t } = useI18n();
  const repos = useRepos();
  const formatErr = useFormatApiError();
  const [params, setParams] = useSearchParams();
  const focusId = params.get("contact") || "";

  const [list, setList] = useState<Contact[]>([]);
  const [total, setTotal] = useState(0);
  const [counts, setCounts] = useState<Record<string, number>>({});
  const [page, setPage] = useState(1);
  const [stageFilter, setStageFilter] = useState<StageFilter>("");
  const [sort, setSort] = useState<SortMode>("last_touch_at");
  const [searchInput, setSearchInput] = useState("");
  const [query, setQuery] = useState("");
  const [err, setErr] = useState<string | null>(null);
  const [msg, setMsg] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [selectedId, setSelectedId] = useState<string | null>(focusId || null);
  const [detail, setDetail] = useState<ContactDetail | null>(null);
  const [note, setNote] = useState("");
  const [amount, setAmount] = useState("");
  const [busy, setBusy] = useState("");

  const load = useCallback(async () => {
    const res = await repos.crm.listContacts({
      page,
      pageSize: PAGE_SIZE,
      query: query || undefined,
      stage: stageFilter && stageFilter !== "needs_follow_up" ? stageFilter : undefined,
      follow_up: stageFilter === "needs_follow_up" ? true : undefined,
      sort,
    });
    setList(res.list);
    setTotal(res.total);
    const nextCounts: Record<string, number> = {};
    for (const item of res.stage_counts) nextCounts[item.stage] = item.count;
    setCounts(nextCounts);
  }, [repos.crm, page, query, stageFilter, sort]);

  useEffect(() => {
    let alive = true;
    setLoading(true);
    load()
      .then(() => {
        if (alive) setErr(null);
      })
      .catch((e) => {
        if (alive) setErr(formatErr(e));
      })
      .finally(() => {
        if (alive) setLoading(false);
      });
    return () => {
      alive = false;
    };
  }, [load]); // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    if (focusId) setSelectedId(focusId);
  }, [focusId]);

  useEffect(() => {
    if (!selectedId) {
      setDetail(null);
      return;
    }
    let alive = true;
    repos.crm
      .getContact(selectedId)
      .then((next) => {
        if (alive) setDetail(next);
      })
      .catch((e) => {
        if (alive) {
          setErr(formatErr(e));
          setSelectedId(null);
          setDetail(null);
        }
      });
    return () => {
      alive = false;
    };
  }, [selectedId, repos.crm]); // eslint-disable-line react-hooks/exhaustive-deps

  const allCount = useMemo(
    () => STAGES.reduce((sum, stage) => sum + (counts[stage] ?? 0), 0),
    [counts],
  );

  async function run(key: string, action: () => Promise<void>, ok?: string) {
    setBusy(key);
    setErr(null);
    setMsg(null);
    try {
      await action();
      await load();
      if (selectedId) setDetail(await repos.crm.getContact(selectedId));
      if (ok) setMsg(ok);
    } catch (e) {
      setErr(formatErr(e));
    } finally {
      setBusy("");
    }
  }

  function selectContact(id: string) {
    setDetail(null);
    setSelectedId(id);
    setParams((current) => {
      const next = new URLSearchParams(current);
      next.set("contact", id);
      return next;
    });
  }

  function closeDetail() {
    setSelectedId(null);
    setDetail(null);
    setParams((current) => {
      const next = new URLSearchParams(current);
      next.delete("contact");
      return next;
    });
  }

  function submitSearch(event: FormEvent) {
    event.preventDefault();
    setPage(1);
    setQuery(searchInput.trim());
  }

  function clearFilters() {
    setSearchInput("");
    setQuery("");
    setStageFilter("");
    setSort("last_touch_at");
    setPage(1);
  }

  async function removeSelected() {
    if (!detail) return;
    const contact = detail.contact;
    if (!window.confirm(t("crm.board.confirmDelete", { name: contact.display_name || `@${contact.author_handle}` }))) {
      return;
    }
    setBusy("delete");
    setErr(null);
    setMsg(null);
    try {
      await repos.crm.deleteContact(contact.id);
      closeDetail();
      if (list.length === 1 && page > 1) {
        setPage((current) => current - 1);
      } else {
        await load();
      }
      setMsg(t("crm.board.msg.deleted"));
    } catch (e) {
      setErr(formatErr(e));
    } finally {
      setBusy("");
    }
  }

  return (
    <>
      <PageHeader title={t("crm.board.title")} />
      <div className="hb-radar-actions hb-radar-actions--toolbar">
        <Link className="hb-btn hb-btn--secondary" to="/app/today">
          {t("crm.board.link.today")}
        </Link>
        <Link className="hb-btn hb-btn--ghost" to="/app/crm/followups">
          {t("crm.board.link.followups")}
        </Link>
        <Link className="hb-btn hb-btn--ghost" to="/app/crm/stats">
          {t("crm.board.link.stats")}
        </Link>
      </div>

      {err ? <p className="hb-banner-error" role="alert">{err}</p> : null}
      {msg ? <p className="hb-banner-ok" role="status">{msg}</p> : null}

      <section className="crm-controls" aria-label={t("crm.board.filters")}>
        <form className="crm-search" onSubmit={submitSearch}>
          <Input
            name="crm-contact-search"
            type="search"
            label={t("crm.board.search")}
            placeholder={t("crm.board.searchPlaceholder")}
            value={searchInput}
            maxLength={80}
            onChange={(event) => setSearchInput(event.target.value)}
          />
          <Button type="submit" variant="secondary">{t("common.search")}</Button>
        </form>
        <Select
          name="crm-stage-filter"
          label={t("crm.board.stageFilter")}
          value={stageFilter}
          onChange={(event) => {
            setStageFilter(event.target.value as StageFilter);
            setPage(1);
          }}
        >
          <option value="">{t("crm.board.allStages")} ({allCount})</option>
          <option value="needs_follow_up">{t("crm.stage.needs_follow_up")} ({counts.needs_follow_up ?? 0})</option>
          {STAGES.map((stage) => (
            <option key={stage} value={stage}>{t(`crm.stage.${stage}`)} ({counts[stage] ?? 0})</option>
          ))}
        </Select>
        <Select
          name="crm-sort"
          label={t("crm.board.sort")}
          value={sort}
          onChange={(event) => {
            setSort(event.target.value as SortMode);
            setPage(1);
          }}
        >
          <option value="last_touch_at">{t("crm.board.sortRecent")}</option>
          <option value="intent_score">{t("crm.board.sortIntent")}</option>
        </Select>
        {query || stageFilter || sort !== "last_touch_at" ? (
          <Button type="button" variant="ghost" onClick={clearFilters}>{t("crm.board.clearFilters")}</Button>
        ) : null}
      </section>

      {loading && !list.length ? <p className="hb-radar-section__hint">{t("common.loading")}</p> : null}

      {!loading && allCount === 0 && !query ? (
        <EmptyState
          title={t("crm.board.empty")}
          description={t("crm.board.emptyHint")}
          action={<Link className="hb-btn hb-btn--secondary" to="/app/today">{t("crm.board.link.today")}</Link>}
        />
      ) : (
        <div className={`crm-workspace${detail ? " crm-workspace--detail" : ""}`}>
          <section className="crm-list-panel">
            <p className="crm-result-count">{t("crm.board.results", { n: total })}</p>
            {!loading && list.length === 0 ? (
              <EmptyState
                title={t("crm.board.noResults")}
                description={t("crm.board.noResultsHint")}
                action={<Button type="button" variant="ghost" onClick={clearFilters}>{t("crm.board.clearFilters")}</Button>}
              />
            ) : (
              <div className="crm-contact-list">
                {list.map((contact) => (
                  <ContactCard
                    key={contact.id}
                    contact={contact}
                    active={selectedId === contact.id}
                    onSelect={selectContact}
                    t={t}
                  />
                ))}
              </div>
            )}
            <Pager total={total} page={page} pageSize={PAGE_SIZE} onPageChange={setPage} />
          </section>

          {detail ? (
            <ContactDetailPanel
              detail={detail}
              amount={amount}
              note={note}
              busy={busy}
              t={t}
              onAmountChange={setAmount}
              onNoteChange={setNote}
              onClose={closeDetail}
              onDelete={() => void removeSelected()}
              onStage={(stage) => void run("stage", async () => {
                await repos.crm.updateStage(detail.contact.id, stage);
              }, t("crm.board.msg.stage"))}
              onFollowUp={() => void run("fu", async () => {
                await repos.crm.setFollowUp(
                  detail.contact.id,
                  !detail.contact.needs_follow_up,
                  detail.contact.follow_up_days || 3,
                );
              }, t("crm.board.msg.followUp"))}
              onWon={() => void run("won", async () => {
                await repos.crm.reportConversion(detail.contact.id, {
                  amount: Number(amount) || 0,
                  currency: "TWD",
                  note: note.trim() || undefined,
                });
              }, t("crm.board.msg.won"))}
              onAddNote={() => void run("note", async () => {
                await repos.crm.addNote(detail.contact.id, note.trim());
                setNote("");
              }, t("crm.board.msg.note"))}
            />
          ) : null}
        </div>
      )}
    </>
  );
}

function ContactCard({
  contact,
  active,
  onSelect,
  t,
}: {
  contact: Contact;
  active: boolean;
  onSelect: (id: string) => void;
  t: (key: string, params?: Record<string, string | number>) => string;
}) {
  return (
    <button
      type="button"
      className={`crm-contact-card${active ? " is-active" : ""}`}
      onClick={() => onSelect(contact.id)}
    >
      <span className="crm-contact-card__head">
        <span>
          <strong>{contact.display_name || `@${contact.author_handle}`}</strong>
          {contact.display_name ? <small>@{contact.author_handle}</small> : null}
        </span>
        <Badge tone={contact.stage === "won" ? "success" : contact.stage === "lost" ? "neutral" : "brand"}>
          {t(`crm.stage.${contact.stage}`)}
        </Badge>
      </span>
      <span className="crm-contact-card__meta">
        <span>{contact.top_intent_score ?? "—"} · {contact.opportunity_count} {t("crm.board.oppCount")}</span>
        {contact.needs_follow_up ? <Badge tone="warning">{t("crm.stage.needs_follow_up")}</Badge> : null}
      </span>
      <small className="crm-contact-card__time">
        {contact.last_touch_at ? t("crm.board.lastTouch", { time: formatTimeAgo(contact.last_touch_at) }) : t("crm.board.noTouch")}
      </small>
    </button>
  );
}

function ContactDetailPanel({
  detail,
  amount,
  note,
  busy,
  t,
  onAmountChange,
  onNoteChange,
  onClose,
  onDelete,
  onStage,
  onFollowUp,
  onWon,
  onAddNote,
}: {
  detail: ContactDetail;
  amount: string;
  note: string;
  busy: string;
  t: (key: string, params?: Record<string, string | number>) => string;
  onAmountChange: (value: string) => void;
  onNoteChange: (value: string) => void;
  onClose: () => void;
  onDelete: () => void;
  onStage: (stage: ContactStage) => void;
  onFollowUp: () => void;
  onWon: () => void;
  onAddNote: () => void;
}) {
  const contact = detail.contact;
  return (
    <aside className="crm-detail">
      <header className="crm-detail__header">
        <div>
          <h2>{contact.display_name || `@${contact.author_handle}`}</h2>
          {contact.display_name ? <p>@{contact.author_handle}</p> : null}
        </div>
        <Button type="button" variant="ghost" onClick={onClose}>{t("common.close")}</Button>
      </header>

      <div className="crm-detail__primary-actions">
        <Select
          name="crm-contact-stage"
          label={t("crm.board.stage")}
          value={contact.stage}
          disabled={busy === "stage"}
          onChange={(event) => onStage(event.target.value as ContactStage)}
        >
          {STAGES.map((stage) => <option key={stage} value={stage}>{t(`crm.stage.${stage}`)}</option>)}
        </Select>
        <Button type="button" variant="secondary" disabled={busy === "fu"} onClick={onFollowUp}>
          {contact.needs_follow_up ? t("crm.board.clearFollowUp") : t("crm.board.markFollowUp")}
        </Button>
      </div>

      <div className="hb-radar-section">
        <h3 className="hb-radar-section__title">{t("crm.board.conversion")}</h3>
        <Input
          name="crm-conversion-amount"
          type="number"
          min="0"
          label={t("crm.board.amount")}
          value={amount}
          onChange={(event) => onAmountChange(event.target.value)}
        />
        <Button type="button" disabled={busy === "won"} onClick={onWon}>{t("crm.board.reportWon")}</Button>
      </div>

      <div className="hb-radar-section">
        <h3 className="hb-radar-section__title">{t("crm.board.notes")}</h3>
        <Textarea name="crm-note" label={t("crm.board.noteLabel")} rows={3} value={note} onChange={(event) => onNoteChange(event.target.value)} />
        <Button type="button" variant="secondary" disabled={busy === "note" || !note.trim()} onClick={onAddNote}>
          {t("crm.board.addNote")}
        </Button>
      </div>

      <div className="hb-radar-section">
        <h3 className="hb-radar-section__title">{t("crm.board.timeline")}</h3>
        {detail.touches.length === 0 ? <p className="hb-radar-section__hint">{t("crm.board.timelineEmpty")}</p> : (
          <ul className="hb-crm-timeline">
            {detail.touches.map((touch) => (
              <li key={touch.id} className="hb-crm-touch">
                <span className="hb-crm-touch__at">{formatTimeAgo(touch.created_at)}</span>
                <span>
                  {touch.type}
                  {touch.product_label_snapshot ? t("crm.board.touchProduct", { label: touch.product_label_snapshot }) : ""}
                  {touch.to_stage ? ` → ${t(`crm.stage.${touch.to_stage}`)}` : ""}
                  {touch.body ? ` · ${touch.body}` : ""}
                </span>
              </li>
            ))}
          </ul>
        )}
      </div>

      {detail.opportunities.length > 0 ? (
        <div className="hb-radar-section">
          <h3 className="hb-radar-section__title">{t("crm.board.opps")}</h3>
          <ul className="radar-list">
            {detail.opportunities.map((opportunity) => (
              <li key={opportunity.id} className="radar-card">
                <Badge tone={opportunity.intent_band === "high" ? "success" : "neutral"}>
                  {opportunity.intent_band} · {opportunity.intent_score}
                </Badge>
                <p className="hb-opp-card__text">{opportunity.text.slice(0, 120)}</p>
                {opportunity.primary_product_label ? (
                  <span className="radar-card__meta">{opportunity.primary_brand_name ? t("crm.board.primaryProductWithBrand", { label: opportunity.primary_product_label, brand: opportunity.primary_brand_name }) : t("crm.board.primaryProduct", { label: opportunity.primary_product_label })}</span>
                ) : <span className="radar-card__meta">{t("crm.board.noProduct")}</span>}
                <a href={opportunity.permalink} target="_blank" rel="noreferrer">{t("radar.today.action.open")}</a>
              </li>
            ))}
          </ul>
        </div>
      ) : null}

      <div className="crm-detail__danger">
        <div>
          <strong>{t("crm.board.deleteTitle")}</strong>
          <p>{t("crm.board.deleteHint")}</p>
        </div>
        <Button type="button" variant="danger" disabled={busy === "delete"} onClick={onDelete}>
          {busy === "delete" ? t("crm.board.deleting") : t("crm.board.delete")}
        </Button>
      </div>
    </aside>
  );
}
