"use client";

import { useEffect, useState, useCallback, useMemo } from "react";
import Link from "next/link";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { EmptyState } from "@/components/ui/empty-state";
import { Skeleton, SkeletonRows } from "@/components/ui/skeleton";
import { Tooltip } from "@/components/ui/tooltip";
import { ALL_ORGANIZATIONS } from "@/lib/sag/entities";
import { snapshotForAgentCall } from "@/lib/agents/context-snapshot";
import type { ThreadClassification, ThreadCategory } from "@/lib/mail/classify-thread";
import { SendEmailButton } from "@/components/app/send-email-button";
import { extractEventHints } from "@/lib/mail/extract-event-hints";
import { CreateCalendarEntryButton } from "@/components/app/create-calendar-entry-button";

interface AccountSummary {
  id: string;
  email: string;
  name?: string;
  entitySlug?: string;
}

interface Message {
  id: string;
  threadId: string;
  subject: string;
  from: string;
  fromEmail: string;
  snippet: string;
  internalDateMs: number;
  unread: boolean;
  hasAttachments: boolean;
  labelIds: string[];
  accountId: string;
  accountEmail: string;
  entitySlug?: string;
  classification?: ThreadClassification;
}

const CATEGORY_CHIP: Record<ThreadCategory, string> = {
  "Action required":
    "bg-red-100 text-red-900 border-red-200 dark:bg-red-900/30 dark:text-red-100 dark:border-red-900/40",
  "FYI":
    "bg-muted text-foreground border-border",
  "Bills & receipts":
    "bg-amber-100 text-amber-900 border-amber-200 dark:bg-amber-900/30 dark:text-amber-100 dark:border-amber-900/40",
  "Bank & financial":
    "bg-green-100 text-green-900 border-green-200 dark:bg-green-900/30 dark:text-green-100 dark:border-green-900/40",
  "Compliance & legal":
    "bg-purple-100 text-purple-900 border-purple-200 dark:bg-purple-900/30 dark:text-purple-100 dark:border-purple-900/40",
  "Vendor / partner":
    "bg-blue-100 text-blue-900 border-blue-200 dark:bg-blue-900/30 dark:text-blue-100 dark:border-blue-900/40",
  "Newsletter":
    "bg-muted/60 text-muted-foreground border-border",
  "Promotion / spam":
    "bg-zinc-200 text-zinc-700 border-zinc-300 dark:bg-zinc-800/60 dark:text-zinc-300 dark:border-zinc-700",
  "Other":
    "bg-muted text-muted-foreground border-border",
};

function ClassificationBadges({ c }: { c: ThreadClassification }) {
  const chipClass = CATEGORY_CHIP[c.category] ?? CATEGORY_CHIP.Other;
  return (
    <>
      {c.urgency === "high" && (
        <span
          className="inline-flex items-center justify-center w-4 h-4 rounded-full bg-red-600 text-white text-[9px] font-bold leading-none shrink-0"
          title="High urgency"
          aria-label="High urgency"
        >
          !
        </span>
      )}
      <span
        className={`inline-flex items-center rounded-full border px-1.5 py-0.5 text-[10px] font-medium leading-none shrink-0 ${chipClass}`}
        title={c.suggestedAction ?? c.category}
      >
        {c.category}
      </span>
      {c.hasDeadline && c.deadlineHint && (
        <span
          className="inline-flex items-center gap-0.5 rounded-full border border-border bg-background px-1.5 py-0.5 text-[10px] text-muted-foreground shrink-0"
          title={`Deadline: ${c.deadlineHint}`}
        >
          <span aria-hidden>📅</span>
          {c.deadlineHint}
        </span>
      )}
    </>
  );
}

interface ThreadDetail {
  id: string;
  subject: string;
  messages: Array<{ id: string; from: string; to: string; date: string; body: string }>;
}

/** Pull the bare email address out of a header value like `Name <addr@host>`. */
function extractEmailAddress(headerValue: string): string {
  const angle = /<([^>]+)>/.exec(headerValue);
  if (angle?.[1]) return angle[1].trim();
  // Fall back to anything that looks like an address.
  const bare = /[^\s<>@]+@[^\s<>@]+\.[^\s<>@]+/.exec(headerValue);
  return bare?.[0]?.trim() ?? headerValue.trim();
}

/**
 * Heuristic: the Secretary Agent's triage output is free-form numbered text.
 * Item (4) typically contains the suggested reply when the email warrants one.
 * We pull a best-effort body out so it can be pre-loaded into the send button.
 * If we can't find a discrete reply section, fall back to the full triage text
 * so the user at least sees what would be sent (and the confirm dialog gives
 * them a final escape).
 */
function extractDraftReply(triage: string): string {
  if (!triage) return "";
  const trimmed = triage.trim();

  // Look for a line starting with "4." (the suggested-action item in the prompt).
  // Capture from there until either item 5 / end of string.
  const match = /(^|\n)\s*4[.)]\s*([\s\S]*?)(?=\n\s*5[.)]|$)/.exec(trimmed);
  if (match?.[2]) {
    const body = match[2].trim();
    // Strip a leading "Suggested action — " style preamble if present.
    return body.replace(/^[^\n]*?(?:reply|response|draft)[^:\n]*:\s*/i, "").trim();
  }

  return trimmed;
}

export function MailInbox() {
  const [accounts, setAccounts] = useState<AccountSummary[]>([]);
  const [messages, setMessages] = useState<Message[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string>("");
  const [accountErrors, setAccountErrors] = useState<Array<{ accountEmail: string; error: string }>>([]);
  const [filterAccount, setFilterAccount] = useState<string>("all");
  const [filterEntity, setFilterEntity] = useState<string>("all");
  const [query, setQuery] = useState("");
  const [selectedThread, setSelectedThread] = useState<{ accountId: string; threadId: string } | null>(null);
  const [threadDetail, setThreadDetail] = useState<ThreadDetail | null>(null);
  const [threadLoading, setThreadLoading] = useState(false);
  const [triageResult, setTriageResult] = useState<string>("");
  const [triaging, setTriaging] = useState(false);

  const fetchMessages = useCallback(async () => {
    setLoading(true);
    setError("");
    try {
      const resp = await fetch("/api/google/messages?max=25");
      const data = await resp.json();
      if (!resp.ok) throw new Error(data.error || "Failed");
      setMessages(data.messages ?? []);
      setAccounts(data.accounts ?? []);
      setAccountErrors(data.errors ?? []);
    } catch (e) {
      setError(e instanceof Error ? e.message : "Unknown error");
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    const t = setTimeout(() => void fetchMessages(), 0);
    return () => clearTimeout(t);
  }, [fetchMessages]);

  const filtered = useMemo(() => {
    return messages.filter((m) => {
      if (filterAccount !== "all" && m.accountId !== filterAccount) return false;
      if (filterEntity !== "all" && m.entitySlug !== filterEntity) return false;
      if (query) {
        const q = query.toLowerCase();
        if (
          !m.subject.toLowerCase().includes(q) &&
          !m.from.toLowerCase().includes(q) &&
          !m.snippet.toLowerCase().includes(q)
        ) {
          return false;
        }
      }
      return true;
    });
  }, [messages, filterAccount, filterEntity, query]);

  async function openThread(m: Message) {
    setSelectedThread({ accountId: m.accountId, threadId: m.threadId });
    setThreadDetail(null);
    setTriageResult("");
    setThreadLoading(true);
    try {
      const resp = await fetch(`/api/google/thread/${m.threadId}?account=${encodeURIComponent(m.accountId)}`);
      const data = await resp.json();
      if (!resp.ok) throw new Error(data.error || "Failed");
      setThreadDetail({ ...data, subject: m.subject });
    } catch (e) {
      setError(e instanceof Error ? e.message : "Failed to load thread");
    } finally {
      setThreadLoading(false);
    }
  }

  async function triage() {
    if (!threadDetail) return;
    setTriaging(true);
    try {
      const combined = threadDetail.messages
        .map((m) => `From: ${m.from}\nDate: ${m.date}\n\n${m.body}`)
        .join("\n\n---\n\n");
      const prompt = `Triage this email thread from a SAG portfolio inbox.

Subject: ${threadDetail.subject}

${combined.slice(0, 12000)}

Return:
1. Classification (Bill / Legal notice / Marketing / Action-required / FYI / Spam)
2. Which SAG module owns this (bills inbox / compliance / HR / archive / etc.)
3. 1-2 sentence summary
4. Suggested action — if it's a deadline, the date; if it's a reply, draft 2-3 sentences
5. Any deadline mentioned in the thread`;

      const resp = await fetch("/api/agents/secretary", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          messages: [{ role: "user", content: prompt }],
          contextSnapshot: snapshotForAgentCall(),
        }),
      });
      const data = await resp.json();
      if (!resp.ok) throw new Error(data.error || "Triage failed");
      setTriageResult(data.message);
    } catch (e) {
      setTriageResult("Triage failed: " + (e instanceof Error ? e.message : "unknown"));
    } finally {
      setTriaging(false);
    }
  }

  if (loading) {
    return (
      <div className="flex-1 p-8">
        <Card>
          <CardContent className="p-6">
            <SkeletonRows rows={6} />
          </CardContent>
        </Card>
      </div>
    );
  }

  if (error && accounts.length === 0) {
    return (
      <div className="flex-1 p-8">
        <Card className="border-destructive/30">
          <CardContent className="p-6">
            <p className="text-sm text-destructive font-medium">Couldn’t load inbox.</p>
            <p className="mt-2 text-xs text-muted-foreground">{error}</p>
            <Button asChild variant="outline" size="sm" className="mt-4">
              <Link href="/app/mail/accounts">Open accounts page</Link>
            </Button>
          </CardContent>
        </Card>
      </div>
    );
  }

  if (accounts.length === 0) {
    return (
      <div className="flex-1 p-8">
        <EmptyState
          icon="📬"
          title="No Gmail accounts connected"
          description="Connect at least one account to see the unified inbox. Each account stays read-only-by-default with refresh tokens stored server-side."
          action={
            <Button asChild variant="brand">
              <Link href="/app/mail/accounts">Connect Gmail →</Link>
            </Button>
          }
        />
      </div>
    );
  }

  return (
    <>
      {/* LEFT: filters + list */}
      <div className="w-full md:w-[480px] border-r flex flex-col bg-background">
        <div className="p-4 border-b space-y-3">
          <div className="flex items-center gap-2">
            <Input
              placeholder="Search subject / sender / snippet..."
              value={query}
              onChange={(e) => setQuery(e.target.value)}
            />
            <Tooltip content="Refresh">
              <Button variant="outline" size="sm" onClick={fetchMessages} aria-label="Refresh">↻</Button>
            </Tooltip>
          </div>
          <div className="flex flex-wrap gap-2">
            <select
              value={filterAccount}
              onChange={(e) => setFilterAccount(e.target.value)}
              className="h-9 rounded-md border border-input bg-background px-2 text-xs flex-1 min-w-[140px]"
            >
              <option value="all">All accounts ({accounts.length})</option>
              {accounts.map((a) => (
                <option key={a.id} value={a.id}>
                  {a.email}
                </option>
              ))}
            </select>
            <select
              value={filterEntity}
              onChange={(e) => setFilterEntity(e.target.value)}
              className="h-9 rounded-md border border-input bg-background px-2 text-xs flex-1 min-w-[140px]"
            >
              <option value="all">All entities</option>
              {ALL_ORGANIZATIONS.map((o) => (
                <option key={o.slug} value={o.slug}>
                  {o.emoji} {o.name}
                </option>
              ))}
            </select>
          </div>
          {accountErrors.length > 0 && (
            <div className="rounded-md border border-yellow-500/30 bg-yellow-50 dark:bg-yellow-900/10 p-2 text-[10px]">
              <strong>Account errors:</strong>{" "}
              {accountErrors.map((e) => `${e.accountEmail}: ${e.error}`).join(" · ")}
            </div>
          )}
          <div className="text-[10px] text-muted-foreground">
            {filtered.length} of {messages.length} messages
          </div>
        </div>

        <div className="flex-1 overflow-y-auto">
          {filtered.length === 0 ? (
            <div className="p-8 text-center text-sm text-muted-foreground">
              No messages match this filter.
            </div>
          ) : (
            <ul>
              {filtered.map((m) => {
                const isSelected = selectedThread?.threadId === m.threadId && selectedThread?.accountId === m.accountId;
                const org = m.entitySlug ? ALL_ORGANIZATIONS.find((o) => o.slug === m.entitySlug) : undefined;
                // MA3: cheap pure-regex scan for date/time hints — render a
                // "📅 Add to calendar" CTA next to the actions row when ≥1 hit.
                // Only takes the first (highest-confidence) hint so the row
                // doesn't sprout multiple buttons.
                const eventHints = extractEventHints(`${m.subject}\n${m.snippet}`);
                const topHint = eventHints[0];
                return (
                  <li
                    key={`${m.accountId}-${m.id}`}
                    onClick={() => openThread(m)}
                    className={`cursor-pointer border-b px-4 py-3 text-sm transition-colors ${
                      isSelected ? "bg-accent" : "hover:bg-accent/50"
                    } ${m.unread ? "font-medium" : ""}`}
                  >
                    <div className="flex items-center justify-between gap-2 mb-0.5">
                      <span className={`truncate ${m.unread ? "" : "text-muted-foreground"}`}>{m.from}</span>
                      <span className="text-[10px] text-muted-foreground shrink-0">
                        {new Date(m.internalDateMs).toLocaleDateString("en-US", { month: "short", day: "numeric" })}
                      </span>
                    </div>
                    <div className="flex items-center gap-1.5 min-w-0">
                      <span className={`truncate ${m.unread ? "font-semibold" : ""}`}>{m.subject}</span>
                    </div>
                    {m.classification && (
                      <div className="mt-1 flex items-center gap-1 flex-wrap">
                        <ClassificationBadges c={m.classification} />
                      </div>
                    )}
                    <div className="mt-0.5 text-xs text-muted-foreground line-clamp-1">{m.snippet}</div>
                    <div className="mt-1.5 flex items-center gap-1.5 flex-wrap">
                      <span className="text-[10px] text-muted-foreground font-mono">{m.accountEmail}</span>
                      {org && <Badge variant="info" className="text-[10px]">{org.emoji}</Badge>}
                      {m.unread && <span className="inline-block w-1.5 h-1.5 rounded-full bg-blue-500" />}
                      {m.hasAttachments && <span title="Attachments">📎</span>}
                      {topHint && (
                        <CreateCalendarEntryButton
                          hint={topHint}
                          threadId={m.threadId}
                          threadSubject={m.subject}
                        />
                      )}
                    </div>
                  </li>
                );
              })}
            </ul>
          )}
        </div>
      </div>

      {/* RIGHT: thread detail */}
      <div className="hidden md:flex flex-1 flex-col bg-muted/10 overflow-hidden">
        {!selectedThread ? (
          <div className="flex-1 flex items-center justify-center text-sm text-muted-foreground">
            Select a message to read and triage it.
          </div>
        ) : threadLoading ? (
          <div className="flex-1 p-6 space-y-4">
            <Skeleton className="h-6 w-1/2" />
            <Skeleton className="h-4 w-1/3" />
            <SkeletonRows rows={4} />
          </div>
        ) : !threadDetail ? (
          <div className="flex-1 flex items-center justify-center text-sm text-destructive">Failed to load</div>
        ) : (
          <>
            <div className="border-b p-5 bg-background">
              <h2 className="text-lg font-semibold">{threadDetail.subject}</h2>
              <p className="mt-0.5 text-xs text-muted-foreground">
                {threadDetail.messages.length} message{threadDetail.messages.length === 1 ? "" : "s"} in thread
              </p>
              <div className="mt-3 flex gap-2 flex-wrap">
                <Button variant="brand" size="sm" disabled={triaging} onClick={triage}>
                  {triaging ? "Triaging..." : "✨ Triage via Secretary Agent"}
                </Button>
                <Button asChild variant="outline" size="sm">
                  <a
                    href={`https://mail.google.com/mail/u/${selectedThread.accountId}/#inbox/${selectedThread.threadId}`}
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    Open in Gmail ↗
                  </a>
                </Button>
              </div>
            </div>

            {triageResult && (() => {
              // Compute the reply target from the most-recent inbound message.
              const lastMsg =
                threadDetail.messages[threadDetail.messages.length - 1];
              const replyTo = lastMsg ? extractEmailAddress(lastMsg.from) : "";
              const replySubject = threadDetail.subject.match(/^re:/i)
                ? threadDetail.subject
                : `Re: ${threadDetail.subject}`;
              const draftBody = extractDraftReply(triageResult);
              const canSend = Boolean(replyTo && draftBody);
              return (
                <div className="border-b p-5 bg-[var(--sag-brand)]/5">
                  <div className="section-label mb-2">Secretary Agent</div>
                  <pre className="whitespace-pre-wrap text-sm font-sans leading-relaxed">{triageResult}</pre>
                  {canSend && (
                    <div className="mt-3 flex items-center gap-2 flex-wrap border-t pt-3">
                      <span className="text-[11px] text-muted-foreground">
                        Reply to <span className="font-mono">{replyTo}</span>
                      </span>
                      <SendEmailButton
                        accountId={selectedThread.accountId}
                        to={replyTo}
                        subject={replySubject}
                        bodyText={draftBody}
                        threadId={selectedThread.threadId}
                      />
                    </div>
                  )}
                </div>
              );
            })()}

            <div className="flex-1 overflow-y-auto p-5 space-y-4">
              {threadDetail.messages.map((msg, i) => (
                <Card key={i}>
                  <CardContent className="p-4">
                    <div className="text-xs text-muted-foreground mb-2 flex items-center justify-between gap-3 flex-wrap">
                      <span><strong>From:</strong> {msg.from}</span>
                      <span>{msg.date}</span>
                    </div>
                    <pre className="whitespace-pre-wrap text-sm font-sans leading-relaxed max-h-[40vh] overflow-y-auto">
                      {msg.body || "(empty body)"}
                    </pre>
                  </CardContent>
                </Card>
              ))}
            </div>
          </>
        )}
      </div>
    </>
  );
}
