"use client";

import Link from "next/link";
import { useCallback, useEffect, useState } from "react";
import { Button } from "@/components/Button";
import { DashboardPageContainer } from "@/components/dashboard/DashboardPageContainer";
import { DashboardShell } from "@/components/dashboard/DashboardShell";
import { EmptyState } from "@/components/ui/EmptyState";
import { ErrorState } from "@/components/ui/ErrorState";
import { PageHeader } from "@/components/ui/PageHeader";
import { notificationsApi, notificationHref } from "@/lib/api/notifications";
import { cn } from "@/lib/cn";
import { formatRelativeTime } from "@/lib/format";
import type { AppNotification } from "@/types/notifications";

type View =
  | { kind: "loading" }
  | { kind: "error"; message: string }
  | { kind: "ready"; notifications: AppNotification[]; page: number; lastPage: number };

export function DashboardNotificationsPage() {
  return (
    <DashboardShell title="Notifications">
      {() => <NotificationsContent />}
    </DashboardShell>
  );
}

function NotificationsContent() {
  const [view, setView] = useState<View>({ kind: "loading" });
  const [markingAll, setMarkingAll] = useState(false);
  const [markingId, setMarkingId] = useState<number | null>(null);

  const load = useCallback(async (page = 1) => {
    setView({ kind: "loading" });
    try {
      const result = await notificationsApi.getNotifications(page, 20);
      setView({
        kind: "ready",
        notifications: result.notifications,
        page: result.meta.current_page,
        lastPage: result.meta.last_page,
      });
    } catch {
      setView({ kind: "error", message: "Unable to load notifications." });
    }
  }, []);

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

  async function markOne(notification: AppNotification) {
    if (notification.read_at !== null || markingId !== null) {
      return;
    }

    setMarkingId(notification.id);
    try {
      const updated = await notificationsApi.markNotificationRead(notification.id);
      setView((current) => {
        if (current.kind !== "ready") {
          return current;
        }

        return {
          ...current,
          notifications: current.notifications.map((item) =>
            item.id === updated.id ? updated : item,
          ),
        };
      });
    } catch {
      // Keep prior state.
    } finally {
      setMarkingId(null);
    }
  }

  async function markAll() {
    if (markingAll || view.kind !== "ready") {
      return;
    }

    setMarkingAll(true);
    try {
      await notificationsApi.markAllNotificationsRead();
      setView((current) => {
        if (current.kind !== "ready") {
          return current;
        }

        const now = new Date().toISOString();

        return {
          ...current,
          notifications: current.notifications.map((item) =>
            item.read_at ? item : { ...item, read_at: now },
          ),
        };
      });
    } catch {
      // Keep prior state.
    } finally {
      setMarkingAll(false);
    }
  }

  const hasUnread =
    view.kind === "ready" && view.notifications.some((item) => item.read_at === null);

  return (
    <DashboardPageContainer>
      <PageHeader
        description="Stay up to date with your campaigns, deliverables, payments, and account activity."
        actions={
          hasUnread ? (
            <Button
              type="button"
              size="sm"
              variant="secondary"
              disabled={markingAll}
              onClick={() => void markAll()}
            >
              Mark all as read
            </Button>
          ) : null
        }
      />

      {view.kind === "loading" ? (
        <div className="space-y-2">
          <div className="h-16 animate-pulse rounded-pv border border-line bg-surface" />
          <div className="h-16 animate-pulse rounded-pv border border-line bg-surface" />
          <div className="h-16 animate-pulse rounded-pv border border-line bg-surface" />
        </div>
      ) : null}

      {view.kind === "error" ? (
        <ErrorState
          title="Unable to load notifications"
          message={view.message}
          onRetry={() => void load(1)}
        />
      ) : null}

      {view.kind === "ready" && view.notifications.length === 0 ? (
        <EmptyState
          title="You're all caught up"
          description="No new notifications right now."
        />
      ) : null}

      {view.kind === "ready" && view.notifications.length > 0 ? (
        <div className="overflow-hidden rounded-pv border border-line bg-surface">
          <ul className="divide-y divide-line">
            {view.notifications.map((notification) => {
              const unread = notification.read_at === null;
              const href = notificationHref(notification);

              return (
                <li key={notification.id}>
                  <div
                    className={cn(
                      "flex flex-col gap-2 px-4 py-3 sm:flex-row sm:items-start sm:justify-between",
                      unread && "bg-bg/60",
                    )}
                  >
                    <div className="min-w-0 flex-1">
                      <div className="flex items-start gap-2.5">
                        <span
                          className={cn(
                            "mt-1.5 size-1.5 shrink-0 rounded-full",
                            unread ? "bg-primary" : "bg-transparent",
                          )}
                          aria-hidden="true"
                        />
                        <div className="min-w-0">
                          <p
                            className={cn(
                              "text-[0.875rem] text-primary",
                              unread ? "font-semibold" : "font-medium",
                            )}
                          >
                            {notification.title}
                          </p>
                          <p className="mt-0.5 text-[0.8125rem] text-ink-60">{notification.body}</p>
                          <p className="mt-1 text-[0.75rem] text-ink-40">
                            {formatRelativeTime(notification.created_at)}
                          </p>
                        </div>
                      </div>
                    </div>
                    <div className="flex shrink-0 items-center gap-2 pl-4 sm:pl-0">
                      {unread ? (
                        <Button
                          type="button"
                          size="sm"
                          variant="secondary"
                          disabled={markingId === notification.id}
                          onClick={() => void markOne(notification)}
                        >
                          Mark read
                        </Button>
                      ) : null}
                      {href ? (
                        <Link
                          href={href}
                          className="inline-flex h-8 items-center rounded-pv border border-line px-2.5 text-[0.75rem] font-medium text-primary transition hover:border-primary"
                          onClick={() => {
                            if (unread) {
                              void markOne(notification);
                            }
                          }}
                        >
                          Open
                        </Link>
                      ) : null}
                    </div>
                  </div>
                </li>
              );
            })}
          </ul>
        </div>
      ) : null}

      {view.kind === "ready" && view.lastPage > 1 ? (
        <div className="mt-4 flex items-center justify-between gap-3">
          <Button
            type="button"
            size="sm"
            variant="secondary"
            disabled={view.page <= 1}
            onClick={() => void load(view.page - 1)}
          >
            Previous
          </Button>
          <p className="text-[0.75rem] text-ink-60">
            Page {view.page} of {view.lastPage}
          </p>
          <Button
            type="button"
            size="sm"
            variant="secondary"
            disabled={view.page >= view.lastPage}
            onClick={() => void load(view.page + 1)}
          >
            Next
          </Button>
        </div>
      ) : null}
    </DashboardPageContainer>
  );
}
