import Link from "next/link";
import NoData from "@/components/ui/NoData";
import { notificationsApi } from "@/lib/api/notifications";
import { getServerUser, requireServerToken } from "@/lib/auth/server";
import type { ApiNotification, PaginationMeta } from "@/lib/api/types";
import {
  deleteSelectedNotifications,
  markNotificationReadById,
} from "./actions";
import UnreadOnlyFilter from "./UnreadOnlyFilter";
import MarkAllReadButton from "./MarkAllReadButton";
import DeleteSelectedButton from "./DeleteSelectedButton";
import DeleteAllButton from "./DeleteAllButton";
import { formatDateTime } from "@/lib/utils";

type PageProps = {
  searchParams: Promise<{ page?: string; unread?: string; role?: string }>;
};

type Role = "buyer" | "seller" | "transporter";
const ROLE_TABS: Array<{ key: Role | ""; label: string }> = [
  { key: "", label: "All" },
  { key: "buyer", label: "Buying" },
  { key: "seller", label: "Selling" },
];

async function loadNotifications(token: string, page: number, unreadOnly: boolean, role?: Role) {
  try {
    return await notificationsApi.list(token, { page, perPage: 20, unreadOnly, role });
  } catch {
    return { data: [] as ApiNotification[], meta: undefined as PaginationMeta | undefined };
  }
}

/**
 * Server-rendered: the cookie token is available during SSR, so the first
 * response already carries the notifications instead of a spinner that waits for
 * hydration before it even asks.
 *
 * Everything from the header buttons down to the list sits inside one form. The
 * row checkboxes are the selection — no `Set` in state — and each action button
 * carries its own `formAction`, which is how four mutations share a single form
 * without nesting (HTML forbids nested forms). The header bell is untouched and
 * still picks up read state on its own poll.
 */
export default async function NotificationsPage({ searchParams }: PageProps) {
  const token = await requireServerToken("/notifications");
  const sp = await searchParams;

  const page = Math.max(1, Number(sp.page) || 1);
  const unreadOnly = sp.unread === "1";
  // Buying and selling messages in separate inboxes (B33).
  const role = (["buyer", "seller", "transporter"] as const).find((r) => r === sp.role);
  const user = await getServerUser();
  const showRoleTabs = Boolean(user?.is_buyer_and_seller);

  const { data: items, meta } = await loadNotifications(token, page, unreadOnly, role);

  const query = (p: number, overrides: { role?: string } = {}) => {
    const params = new URLSearchParams();
    if (unreadOnly) params.set("unread", "1");
    const r = "role" in overrides ? overrides.role : role;
    if (r) params.set("role", r);
    params.set("page", String(p));
    return `/notifications?${params.toString()}`;
  };

  return (
    <div className="rounded-xl bg-white p-6 shadow-sm ring-1 ring-gray-100">
      <form action={deleteSelectedNotifications}>
        <div className="flex flex-wrap items-center justify-between gap-3 border-b border-gray-100 pb-4">
          <div className="flex flex-wrap items-center gap-3">
            <h1 className="text-xl font-semibold text-gray-900">Notifications</h1>
            {showRoleTabs && (
              <nav className="flex rounded-lg bg-gray-100 p-0.5 text-sm" aria-label="Inbox">
                {ROLE_TABS.map((t) => (
                  <Link
                    key={t.key || "all"}
                    href={query(1, { role: t.key })}
                    className={`rounded-md px-3 py-1 font-medium ${(role ?? "") === t.key ? "bg-white text-[#CC1414] shadow-sm" : "text-gray-600 hover:text-gray-900"}`}
                  >
                    {t.label}
                  </Link>
                ))}
              </nav>
            )}
          </div>
          <div className="flex flex-wrap items-center gap-2">
            <UnreadOnlyFilter value={unreadOnly} />
            <MarkAllReadButton />
            <DeleteSelectedButton />
            <DeleteAllButton />
            <a
              href="/notifications/settings"
              className="rounded-lg bg-[#CC1414] px-3 py-1.5 text-sm font-medium text-white hover:bg-[#a51010]"
            >
              Settings
            </a>
          </div>
        </div>

        {items.length === 0 ? (
          <NoData title="No notifications" message="You're all caught up." />
        ) : (
          <ul className="divide-y divide-gray-100">
            {items.map((n) => (
              <li key={n.id} className="flex items-start gap-3 py-4">
                <input
                  type="checkbox"
                  name="id"
                  value={n.id}
                  className="mt-1 h-4 w-4 rounded border-gray-300 text-[#CC1414] focus:ring-[#CC1414]"
                />
                <div className="flex-1">
                  <div className="flex items-start justify-between gap-3">
                    <div>
                      <div className="flex items-center gap-2">
                        {/* Opens the RFQ / order it is about (B33). */}
                        {n.link ? (
                          <Link href={n.link} className="text-sm font-semibold text-gray-900 hover:text-[#CC1414] hover:underline">
                            {n.title ?? "Notification"}
                          </Link>
                        ) : (
                          <p className="text-sm font-semibold text-gray-900">{n.title ?? "Notification"}</p>
                        )}
                        {n.role && (
                          <span className="rounded-full bg-gray-100 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-gray-500">
                            {n.role === "buyer" ? "Buying" : n.role === "seller" ? "Selling" : "Transport"}
                          </span>
                        )}
                        {!n.is_read && (
                          <span className="inline-block h-2 w-2 rounded-full bg-[#CC1414]" aria-label="Unread" />
                        )}
                      </div>
                      {n.body && <p className="mt-0.5 text-sm text-gray-600">{n.body}</p>}
                      {n.created_at && (
                        <p className="mt-1 text-xs text-gray-400">{formatDateTime(n.created_at)}</p>
                      )}
                    </div>
                    {!n.is_read && (
                      /* The row id is bound into the server action, so marking one
                         read needs no client JS — and no name/value pair, which
                         React overrides on a button with a function formAction. */
                      <button
                        type="submit"
                        formAction={markNotificationReadById.bind(null, n.id)}
                        className="shrink-0 text-xs font-medium text-[#CC1414] hover:underline"
                      >
                        Mark read
                      </button>
                    )}
                  </div>
                </div>
              </li>
            ))}
          </ul>
        )}
      </form>

      {meta && meta.last_page > 1 && (
        <div className="mt-4 flex flex-wrap items-center justify-between gap-3 rounded-xl bg-white px-4 py-3 shadow-sm ring-1 ring-gray-100">
          <span className="min-w-0 truncate text-sm text-gray-500">
            Page {meta.current_page} of {meta.last_page} · {meta.total} total
          </span>
          {/* Plain links: no client JS needed for paging. */}
          <div className="flex gap-2">
            {page > 1 ? (
              <Link href={query(page - 1)} className="rounded-md border px-4 py-2 text-sm hover:bg-gray-50">
                Prev
              </Link>
            ) : (
              <span className="rounded-md border px-4 py-2 text-sm opacity-50">Prev</span>
            )}
            {page < meta.last_page ? (
              <Link href={query(page + 1)} className="rounded-md border px-4 py-2 text-sm hover:bg-gray-50">
                Next
              </Link>
            ) : (
              <span className="rounded-md border px-4 py-2 text-sm opacity-50">Next</span>
            )}
          </div>
        </div>
      )}
    </div>
  );
}
