import type { Metadata } from "next";
import Link from "next/link";
import { OrderMode, Prisma, SubscriptionStatus } from "@prisma/client";
import { CalendarClock, CheckCheck, PauseCircle, Repeat2, Users } from "lucide-react";
import { Button } from "@/components/ui/button";
import { EmptyState } from "@/components/shared/empty-state";
import { PageHeader } from "@/components/shared/page-header";
import { FilterTabs } from "@/components/panel/bulk/filter-tabs";
import { Pager } from "@/components/panel/bulk/pager";
import { StatCard } from "@/components/panel/bulk/stat-card";
import {
  SubscriptionsTable,
  type SubscriptionRowDTO,
} from "@/components/panel/bulk/subscriptions-table";
import { db } from "@/lib/db";
import { requireUser } from "@/lib/guards";
import { formatNumber } from "@/lib/format";
import { bulkTexts } from "@/lib/i18n/bulk";
import { FINAL_ORDER_STATUSES } from "@/lib/orders";
import { partialRefundAmount } from "@/lib/pricing";
import { iso, money } from "@/lib/serialize";
import { subscriptionProgress } from "@/lib/validation/bulk";

export const metadata: Metadata = { title: "Subscriptions" };

const PER_PAGE = 20;

const STATUS_FILTERS: {
  value: string;
  label: string;
  status?: SubscriptionStatus;
}[] = [
  { value: "all", label: bulkTexts.filterAll },
  { value: "active", label: bulkTexts.filterActive, status: SubscriptionStatus.ACTIVE },
  { value: "paused", label: bulkTexts.filterPaused, status: SubscriptionStatus.PAUSED },
  {
    value: "completed",
    label: bulkTexts.filterCompleted,
    status: SubscriptionStatus.COMPLETED,
  },
  { value: "expired", label: bulkTexts.filterExpired, status: SubscriptionStatus.EXPIRED },
  {
    value: "canceled",
    label: bulkTexts.filterCanceled,
    status: SubscriptionStatus.CANCELED,
  },
];

function shortId(id: string): string {
  return id.length <= 12 ? id : `…${id.slice(-8)}`;
}

export default async function SubscriptionsPage(props: {
  searchParams: Promise<{ status?: string; page?: string }>;
}) {
  const user = await requireUser();
  const searchParams = await props.searchParams;

  const filterValue = (searchParams.status ?? "all").toLowerCase();
  const filter =
    STATUS_FILTERS.find((f) => f.value === filterValue) ?? STATUS_FILTERS[0];
  const page = Math.max(1, Math.trunc(Number(searchParams.page ?? 1)) || 1);

  const scope: Prisma.SubscriptionWhereInput = { userId: user.id };
  const where: Prisma.SubscriptionWhereInput = filter.status
    ? { ...scope, status: filter.status }
    : scope;

  const [all, counts, total, rows] = await Promise.all([
    db.subscription.findMany({
      where: scope,
      select: {
        username: true,
        postsDelivered: true,
        oldPostsDelivered: true,
        status: true,
      },
    }),
    db.subscription.groupBy({
      by: ["status"],
      where: scope,
      _count: { _all: true },
    }),
    db.subscription.count({ where }),
    db.subscription.findMany({
      where,
      orderBy: { createdAt: "desc" },
      skip: (page - 1) * PER_PAGE,
      take: PER_PAGE,
      include: { service: { select: { id: true, name: true } } },
    }),
  ]);

  // The upfront charge for a subscription lives on the first SUBSCRIPTION-mode order
  // created with it. Only orders still open can carry an undelivered refund.
  const upfrontBySub = new Map<
    string,
    { id: number; charge: Prisma.Decimal; quantity: number }
  >();
  if (rows.length) {
    const upfrontOrders = await db.order.findMany({
      where: {
        subscriptionId: { in: rows.map((r) => r.id) },
        mode: OrderMode.SUBSCRIPTION,
        status: { notIn: FINAL_ORDER_STATUSES },
      },
      orderBy: { id: "asc" },
      select: { id: true, subscriptionId: true, charge: true, quantity: true },
    });
    for (const order of upfrontOrders) {
      if (!order.subscriptionId) continue;
      if (upfrontBySub.has(order.subscriptionId)) continue;
      upfrontBySub.set(order.subscriptionId, {
        id: order.id,
        charge: order.charge,
        quantity: order.quantity,
      });
    }
  }

  const countByStatus = new Map(
    counts.map((c) => [c.status, c._count._all] as const),
  );
  const totalCount = all.length;
  const postsCovered = all.reduce(
    (acc, s) => acc + s.postsDelivered + s.oldPostsDelivered,
    0,
  );
  const profiles = new Set(all.map((s) => s.username.toLowerCase())).size;

  const now = Date.now();
  const dtos: SubscriptionRowDTO[] = rows.map((row) => {
    const progress = subscriptionProgress(row);
    const upfront = upfrontBySub.get(row.id);
    const refundQuantity =
      upfront && upfront.quantity > 0
        ? Math.min(progress.undeliveredQuantity, upfront.quantity)
        : 0;
    const refund = upfront
      ? partialRefundAmount(upfront.charge, upfront.quantity, refundQuantity)
      : new Prisma.Decimal(0);
    const expired = row.expiryAt ? row.expiryAt.getTime() < now : false;

    return {
      id: row.id,
      shortId: shortId(row.id),
      username: row.username,
      minQuantity: row.minQuantity,
      maxQuantity: row.maxQuantity,
      posts: row.posts,
      postsDelivered: row.postsDelivered,
      oldPosts: row.oldPosts,
      oldPostsDelivered: row.oldPostsDelivered,
      delayMinutes: row.delayMinutes,
      serviceId: row.service.id,
      serviceName: row.service.name,
      status: row.status,
      createdAt: iso(row.createdAt),
      updatedAt: iso(row.updatedAt),
      expiryAt: iso(row.expiryAt),
      undeliveredPosts: progress.undeliveredPosts,
      refundEstimate: money(refund),
      canPause: row.status === SubscriptionStatus.ACTIVE,
      canResume: row.status === SubscriptionStatus.PAUSED && !expired,
      canCancel:
        row.status === SubscriptionStatus.ACTIVE ||
        row.status === SubscriptionStatus.PAUSED,
    };
  });

  const tabs = STATUS_FILTERS.map((f) => ({
    value: f.value,
    label: f.label,
    count: f.status ? (countByStatus.get(f.status) ?? 0) : totalCount,
  }));

  return (
    <div className="mx-auto w-full max-w-screen-2xl p-4 sm:p-6">
      <PageHeader
        title={bulkTexts.subsTitle}
        description={bulkTexts.subsSubtitle}
        icon={Repeat2}
        actions={
          <Button asChild size="lg">
            <Link href="/">{bulkTexts.subsNewOrder}</Link>
          </Button>
        }
      />

      {totalCount > 0 ? (
        <div className="mb-6 grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
          <StatCard
            label={bulkTexts.subsStatActive}
            value={formatNumber(countByStatus.get(SubscriptionStatus.ACTIVE) ?? 0)}
            icon={CalendarClock}
            tone="emerald"
          />
          <StatCard
            label={bulkTexts.subsStatPaused}
            value={formatNumber(countByStatus.get(SubscriptionStatus.PAUSED) ?? 0)}
            icon={PauseCircle}
            tone="amber"
          />
          <StatCard
            label={bulkTexts.subsStatPostsCovered}
            value={formatNumber(postsCovered)}
            icon={CheckCheck}
            tone="cyan"
          />
          <StatCard
            label={bulkTexts.subsStatProfiles}
            value={formatNumber(profiles)}
            icon={Users}
            tone="violet"
          />
        </div>
      ) : null}

      {totalCount === 0 ? (
        <EmptyState
          icon={Repeat2}
          title={bulkTexts.subsEmptyTitle}
          hint={bulkTexts.subsEmptyHint}
          action={
            <Button asChild>
              <Link href="/">{bulkTexts.subsNewOrder}</Link>
            </Button>
          }
        />
      ) : (
        <>
          <FilterTabs basePath="/subscriptions" current={filter.value} options={tabs} />
          <div className="overflow-hidden rounded-2xl border bg-card shadow-sm">
            {dtos.length === 0 ? (
              <p className="px-4 py-14 text-center text-sm text-muted-foreground">
                {bulkTexts.subsEmptyTitle}
              </p>
            ) : (
              <SubscriptionsTable rows={dtos} />
            )}
            <Pager
              basePath="/subscriptions"
              params={{ status: filter.value === "all" ? undefined : filter.value }}
              page={page}
              perPage={PER_PAGE}
              total={total}
            />
          </div>
        </>
      )}
    </div>
  );
}
