import type { LoaderFunctionArgs } from "react-router";
import { Link, useLoaderData } from "react-router";

import { authenticate } from "../shopify.server";
import db from "../db.server";

export const loader = async ({ request }: LoaderFunctionArgs) => {
  const { session } = await authenticate.admin(request);

  const [settings, recent, counts] = await Promise.all([
    db.shopSettings.findUnique({ where: { shopDomain: session.shop } }),
    db.invoice.findMany({
      where: { shopDomain: session.shop },
      orderBy: [{ issuedAt: "desc" }],
      take: 8,
    }),
    db.invoice.groupBy({
      by: ["status"],
      where: { shopDomain: session.shop },
      _count: { _all: true },
    }),
  ]);

  const total = counts.reduce((acc, row) => acc + row._count._all, 0);
  const issuedCount = counts.find((c) => c.status === "issued")?._count._all ?? 0;
  const sentCount = counts.find((c) => c.status === "sent")?._count._all ?? 0;
  const cancelledCount = counts.find((c) => c.status === "cancelled")?._count._all ?? 0;

  const settingsConfigured = !!(
    settings &&
    settings.companyName &&
    settings.addressLine1 &&
    settings.iban
  );

  return {
    settingsConfigured,
    metrics: { total, issuedCount, sentCount, cancelledCount },
    recent: recent.map((i) => ({
      id: i.id,
      number: i.invoiceNumber,
      kind: i.kind,
      orderName: i.orderName,
      version: i.version,
      status: i.status,
      sentAt: i.sentAt?.toISOString() ?? null,
      cancelledAt: i.cancelledAt?.toISOString() ?? null,
      issuedAt: i.issuedAt.toISOString(),
      pdfUrl: i.pdfUrl,
    })),
  };
};

const dateFmt = new Intl.DateTimeFormat("en-GB", {
  day: "2-digit",
  month: "short",
  year: "numeric",
});

function formatDate(iso: string | null): string {
  if (!iso) return "—";
  return dateFmt.format(new Date(iso));
}

interface RecentInvoice {
  id: string;
  number: string;
  kind: string;
  orderName: string;
  version: number;
  status: string;
  sentAt: string | null;
  cancelledAt: string | null;
  issuedAt: string;
  pdfUrl: string;
}

function statusBadge(invoice: RecentInvoice): {
  tone: "success" | "info" | "critical" | "warning";
  label: string;
} {
  if (invoice.cancelledAt) return { tone: "critical", label: "Cancelled" };
  if (invoice.kind === "storno") return { tone: "warning", label: "Storno" };
  if (invoice.sentAt) return { tone: "success", label: "Sent" };
  return { tone: "info", label: "Issued" };
}

export default function Index() {
  const { settingsConfigured, metrics, recent } = useLoaderData<typeof loader>();

  return (
    <s-page heading="LinumIQ Invoice">
      {!settingsConfigured && (
        <s-banner tone="warning" heading="Configure your invoice settings">
          <s-paragraph>
            Complete your company, bank and numbering details so generated
            invoices are legally compliant.
          </s-paragraph>
          <s-stack direction="inline" gap="base">
            <s-link href="/app/settings">Open settings →</s-link>
          </s-stack>
        </s-banner>
      )}

      <s-section heading="Overview">
        <s-grid gridTemplateColumns="repeat(4, minmax(0, 1fr))" gap="base">
          <Metric label="Total invoices" value={metrics.total} />
          <Metric label="Issued" value={metrics.issuedCount} tone="info" />
          <Metric label="Sent" value={metrics.sentCount} tone="success" />
          <Metric label="Cancelled" value={metrics.cancelledCount} tone="critical" />
        </s-grid>
      </s-section>

      <s-section
        heading="Recent invoices"
        padding="none"
        accessibilityLabel="Recent invoices table"
      >
        {recent.length === 0 ? (
          <s-box padding="base">
            <s-stack direction="block" gap="base" alignItems="center">
              <s-text type="strong">No invoices yet</s-text>
              <s-paragraph tone="neutral">
                Generate your first invoice from the Invoices page or directly
                from a Shopify order.
              </s-paragraph>
              <s-link href="/app/invoices">Open invoices →</s-link>
            </s-stack>
          </s-box>
        ) : (
          <s-table>
            <s-table-header-row>
              <s-table-header listSlot="primary">Invoice</s-table-header>
              <s-table-header>Order</s-table-header>
              <s-table-header>Issued</s-table-header>
              <s-table-header listSlot="secondary">Status</s-table-header>
              <s-table-header listSlot="labeled">PDF</s-table-header>
            </s-table-header-row>
            <s-table-body>
              {recent.map((invoice) => {
                const badge = statusBadge(invoice);
                return (
                  <s-table-row key={invoice.id}>
                    <s-table-cell>
                      <s-stack direction="block" gap="none">
                        <s-text type="strong">{invoice.number}</s-text>
                        {invoice.version > 1 ? (
                          <s-text tone="neutral">v{invoice.version}</s-text>
                        ) : null}
                      </s-stack>
                    </s-table-cell>
                    <s-table-cell>{invoice.orderName}</s-table-cell>
                    <s-table-cell>{formatDate(invoice.issuedAt)}</s-table-cell>
                    <s-table-cell>
                      <s-badge tone={badge.tone}>{badge.label}</s-badge>
                    </s-table-cell>
                    <s-table-cell>
                      <s-stack direction="inline" gap="small" justifyContent="end">
                        {invoice.pdfUrl ? (
                          <s-link href={invoice.pdfUrl} target="_blank">
                            Open
                          </s-link>
                        ) : (
                          <s-text tone="neutral">—</s-text>
                        )}
                      </s-stack>
                    </s-table-cell>
                  </s-table-row>
                );
              })}
            </s-table-body>
          </s-table>
        )}
        <s-box padding="base">
          <s-stack direction="inline" justifyContent="end">
            <Link to="/app/invoices">View all invoices →</Link>
          </s-stack>
        </s-box>
      </s-section>

      <s-section heading="How it works">
        <s-stack direction="block" gap="base">
          <s-paragraph>
            LinumIQ Invoice generates Austrian-compliant PDF invoices for your
            Shopify orders. PDFs are stored on Shopify Files and linked to
            each order via metafields.
          </s-paragraph>
          <s-paragraph tone="neutral">
            Trigger generation from the order page (Generate invoice action),
            via Shopify Flow, or in bulk from the Invoices page.
          </s-paragraph>
        </s-stack>
      </s-section>
    </s-page>
  );
}

function Metric({
  label,
  value,
  tone,
}: {
  label: string;
  value: number;
  tone?: "info" | "success" | "critical";
}) {
  const valueTone = tone ?? "neutral";
  return (
    <s-box padding="base" background="subdued" border="base" borderRadius="base">
      <s-stack direction="block" gap="small">
        <s-text tone="neutral">{label}</s-text>
        <s-heading>
          <s-text tone={valueTone}>{value}</s-text>
        </s-heading>
      </s-stack>
    </s-box>
  );
}
