import { useCallback, useEffect, useMemo, useState } from "react";
import { createFileRoute, Link } from "@tanstack/react-router";
import { useServerFn } from "@tanstack/react-start";
import {
  Inbox,
  Loader2,
  Mail,
  Paperclip,
  PenSquare,
  RefreshCw,
  Send,
  Star,
  Trash2,
} from "lucide-react";
import { toast } from "sonner";
import {
  attachmentUrl,
  deleteMail,
  listMail,
  markMailRead,
  toggleMailStar,
  type MailRow,
} from "@/lib/mail.functions";

export const Route = createFileRoute("/_authenticated/mail/")({
  head: () => ({
    meta: [
      { title: "GataMail Inbox — Gatavase Corporation" },
      {
        name: "description",
        content:
          "Your GataMail inbox: read received messages, star and manage mail, and compose new email from your Gatavase account.",
      },
      { property: "og:title", content: "GataMail Inbox — Gatavase" },
      { property: "og:description", content: "Secure GataMail inbox for Gatavase accounts." },
      { property: "og:type", content: "website" },
      { name: "twitter:card", content: "summary" },
    ],
  }),
  component: MailInbox,
});

function timeLabel(iso: string) {
  const d = new Date(iso);
  const today = new Date();
  const sameDay = d.toDateString() === today.toDateString();
  return sameDay
    ? d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
    : d.toLocaleDateString([], { day: "2-digit", month: "short" });
}

function MailInbox() {
  const load = useServerFn(listMail);
  const readFn = useServerFn(markMailRead);
  const starFn = useServerFn(toggleMailStar);
  const removeFn = useServerFn(deleteMail);
  const signFn = useServerFn(attachmentUrl);

  const [messages, setMessages] = useState<MailRow[]>([]);
  const [account, setAccount] = useState("");
  const [folder, setFolder] = useState<"inbox" | "sent">("inbox");
  const [query, setQuery] = useState("");
  const [openId, setOpenId] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);

  const refresh = useCallback(async () => {
    setLoading(true);
    try {
      const res = await load({});
      setMessages(res.messages);
      setAccount(res.email);
    } catch {
      toast.error("Could not load your mailbox.");
    } finally {
      setLoading(false);
    }
  }, [load]);

  useEffect(() => {
    void refresh();
  }, [refresh]);

  const visible = useMemo(() => {
    const q = query.trim().toLowerCase();
    return messages
      .filter((m) => m.folder === folder)
      .filter(
        (m) =>
          !q ||
          m.subject.toLowerCase().includes(q) ||
          m.body.toLowerCase().includes(q) ||
          m.from_email.toLowerCase().includes(q) ||
          m.to_emails.join(" ").toLowerCase().includes(q),
      );
  }, [messages, folder, query]);

  const open = messages.find((m) => m.id === openId) ?? null;
  const unread = messages.filter((m) => m.folder === "inbox" && !m.read).length;

  const onOpen = async (m: MailRow) => {
    setOpenId(m.id);
    if (!m.read) {
      setMessages((prev) => prev.map((x) => (x.id === m.id ? { ...x, read: true } : x)));
      await readFn({ data: { id: m.id, read: true } }).catch(() => {});
    }
  };

  const onStar = async (m: MailRow) => {
    setMessages((prev) =>
      prev.map((x) => (x.id === m.id ? { ...x, starred: !x.starred } : x)),
    );
    await starFn({ data: { id: m.id, starred: !m.starred } }).catch(() => {});
  };

  const onDelete = async (m: MailRow) => {
    setMessages((prev) => prev.filter((x) => x.id !== m.id));
    if (openId === m.id) setOpenId(null);
    await removeFn({ data: { id: m.id } }).catch(() => {});
    toast.success("Message deleted");
  };

  const openAttachment = async (path: string) => {
    try {
      const { url } = await signFn({ data: { path } });
      if (url) window.open(url, "_blank", "noopener");
    } catch {
      toast.error("Attachment unavailable.");
    }
  };

  return (
    <div className="mx-auto max-w-6xl px-5 py-12">
      <div className="flex flex-wrap items-end justify-between gap-4">
        <div>
          <p className="font-mono text-xs uppercase tracking-[0.2em] text-primary">GataMail</p>
          <h1 className="mt-2 text-3xl font-bold md:text-4xl">Inbox</h1>
          <p className="mt-2 text-sm text-muted-foreground">
            {account ? `Signed in as ${account}` : "Secure Gatavase mailbox"} · {unread} unread
          </p>
        </div>
        <div className="flex gap-2">
          <button
            onClick={() => void refresh()}
            className="inline-flex items-center gap-2 rounded-full border border-input px-4 py-2 text-sm"
          >
            <RefreshCw className={`size-4 ${loading ? "animate-spin" : ""}`} /> Refresh
          </button>
          <Link
            to="/mail/compose"
            className="inline-flex items-center gap-2 rounded-full bg-primary px-5 py-2 text-sm font-semibold text-primary-foreground"
          >
            <PenSquare className="size-4" /> Compose
          </Link>
        </div>
      </div>

      <div className="mt-8 grid gap-5 lg:grid-cols-[300px_1fr]">
        <aside className="space-y-4">
          <div className="rounded-2xl border border-border bg-card/60 p-2 backdrop-blur">
            {(
              [
                { key: "inbox", label: "Inbox", icon: Inbox },
                { key: "sent", label: "Sent", icon: Send },
              ] as const
            ).map(({ key, label, icon: Icon }) => (
              <button
                key={key}
                onClick={() => {
                  setFolder(key);
                  setOpenId(null);
                }}
                className={`flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-sm transition-colors ${
                  folder === key
                    ? "bg-primary/15 text-primary"
                    : "text-muted-foreground hover:text-foreground"
                }`}
              >
                <Icon className="size-4" />
                {label}
                <span className="ml-auto font-mono text-xs">
                  {messages.filter((m) => m.folder === key).length}
                </span>
              </button>
            ))}
          </div>
          <input
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Search mail"
            className="w-full rounded-xl border border-input bg-background px-4 py-2.5 text-sm"
          />
        </aside>

        <section className="min-h-[420px] rounded-2xl border border-border bg-card/60 backdrop-blur">
          {loading ? (
            <div className="flex h-64 items-center justify-center text-muted-foreground">
              <Loader2 className="size-5 animate-spin" />
            </div>
          ) : open ? (
            <article className="p-6">
              <button
                onClick={() => setOpenId(null)}
                className="text-xs font-mono uppercase tracking-widest text-primary"
              >
                ← Back to {folder}
              </button>
              <h2 className="mt-4 text-2xl font-semibold">{open.subject || "(no subject)"}</h2>
              <p className="mt-2 text-sm text-muted-foreground">
                From <span className="text-foreground">{open.from_email}</span> · To{" "}
                {open.to_emails.join(", ")} · {new Date(open.created_at).toLocaleString()}
              </p>
              <div className="mt-6 whitespace-pre-wrap text-sm leading-relaxed">{open.body}</div>
              {open.attachments.length > 0 && (
                <div className="mt-6 flex flex-wrap gap-2">
                  {open.attachments.map((a) => (
                    <button
                      key={a.path}
                      onClick={() => void openAttachment(a.path)}
                      className="inline-flex items-center gap-2 rounded-full border border-input px-3 py-1.5 text-xs"
                    >
                      <Paperclip className="size-3.5" /> {a.name}
                    </button>
                  ))}
                </div>
              )}
              <div className="mt-8 flex gap-2">
                <button
                  onClick={() => void onStar(open)}
                  className="inline-flex items-center gap-2 rounded-full border border-input px-4 py-2 text-xs"
                >
                  <Star className={`size-3.5 ${open.starred ? "fill-primary text-primary" : ""}`} />
                  {open.starred ? "Starred" : "Star"}
                </button>
                <button
                  onClick={() => void onDelete(open)}
                  className="inline-flex items-center gap-2 rounded-full border border-destructive/40 px-4 py-2 text-xs text-destructive"
                >
                  <Trash2 className="size-3.5" /> Delete
                </button>
              </div>
            </article>
          ) : visible.length === 0 ? (
            <div className="flex h-64 flex-col items-center justify-center gap-3 text-center text-muted-foreground">
              <Mail className="size-8 text-primary/60" />
              <p className="text-sm">No messages in {folder}.</p>
              <Link to="/mail/compose" className="text-sm font-semibold text-primary">
                Compose your first message
              </Link>
            </div>
          ) : (
            <ul className="divide-y divide-border">
              {visible.map((m) => (
                <li key={m.id}>
                  <div className="flex items-center gap-3 px-4 py-3 transition-colors hover:bg-primary/5">
                    <button
                      onClick={() => void onStar(m)}
                      aria-label="Star message"
                      className="text-muted-foreground"
                    >
                      <Star className={`size-4 ${m.starred ? "fill-primary text-primary" : ""}`} />
                    </button>
                    <button
                      onClick={() => void onOpen(m)}
                      className="min-w-0 flex-1 text-left"
                    >
                      <div className="flex items-center gap-2">
                        <span
                          className={`truncate text-sm ${m.read ? "text-muted-foreground" : "font-semibold"}`}
                        >
                          {folder === "inbox" ? m.from_email : m.to_emails.join(", ")}
                        </span>
                        {!m.read && folder === "inbox" && (
                          <span className="size-1.5 rounded-full bg-primary" />
                        )}
                      </div>
                      <p className="truncate text-sm">
                        {m.subject || "(no subject)"}{" "}
                        <span className="text-muted-foreground">— {m.body.slice(0, 80)}</span>
                      </p>
                    </button>
                    {m.attachments.length > 0 && (
                      <Paperclip className="size-3.5 text-muted-foreground" />
                    )}
                    <span className="font-mono text-[11px] text-muted-foreground">
                      {timeLabel(m.created_at)}
                    </span>
                  </div>
                </li>
              ))}
            </ul>
          )}
        </section>
      </div>
    </div>
  );
}
