import type { LoaderFunctionArgs } from "react-router";
import { useLoaderData, useNavigate, useSearchParams } from "react-router";
import React from "react";
import {
  Page,
  Card,
  Text,
  BlockStack,
  InlineGrid,
  DataTable,
  Select,
  Badge,
  InlineStack,
  Box,
} from "@shopify/polaris";
import { useState, useMemo } from "react";
import { authenticate } from "../shopify.server";
import prisma from "../db.server";

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

  // Fetch shop currency code
  let currencyCode = "USD";
  try {
    const shopResp = await admin.graphql(`#graphql query { shop { currencyCode } }`);
    const shopJson = await shopResp.json() as any;
    currencyCode = shopJson?.data?.shop?.currencyCode ?? "USD";
  } catch { /* fall back to USD */ }
  const url  = new URL(request.url);
  const range = url.searchParams.get("range") ?? "month";

  const now = new Date();
  let since = new Date();
  if      (range === "week")  since.setDate(now.getDate() - 7);
  else if (range === "month") since.setMonth(now.getMonth() - 1);
  else if (range === "year")  since.setFullYear(now.getFullYear() - 1);
  else                        since = new Date(0); // "all" — beginning of time
  since.setHours(0, 0, 0, 0);

  // Summary totals
  const summary = await prisma.dealAnalytics.aggregate({
    where: { shop, runDate: { gte: since } },
    _sum: { unitsSold: true, revenue: true, impressions: true },
  });

  // All individual deal runs in range — most recent first
  const runs = await prisma.dealAnalytics.findMany({
    where: { shop, runDate: { gte: since } },
    include: { dealSlot: true },
    orderBy: { runDate: "desc" },
    take: 500,
  });

  const rows = runs.map((r) => {
    const slot = r.dealSlot;
    const numericId = slot?.productId?.replace("gid://shopify/Product/", "") ?? "—";
    const discount =
      slot?.discountType === "percentage"
        ? `${slot.discountValue}%`
        : `$${slot?.discountValue?.toFixed(2) ?? "0.00"}`;

    return {
      runDate:       r.runDate,
      productId:     numericId,
      sku:           slot?.productSku   ?? "—",
      title:         slot?.productTitle ?? "Deleted product",
      originalPrice: slot?.originalPrice ?? 0,
      discountType:  slot?.discountType ?? "percentage",
      discountValue: slot?.discountValue ?? 0,
      discountLabel: discount,
      unitsSold:     r.unitsSold,
      revenue:       r.revenue,
      startHour:     slot?.startHour ?? 0,
      specificDate:  slot?.specificDate ?? null,
    };
  });

  return {
    range,
    currencyCode,
    summary: {
      unitsSold:   summary._sum.unitsSold   ?? 0,
      revenue:     summary._sum.revenue     ?? 0,
      impressions: summary._sum.impressions ?? 0,
      dealsRun:    runs.length,
    },
    rows,
  };
};

export default function Analytics() {
  const { summary, rows, range, currencyCode } = useLoaderData<typeof loader>();
  const navigate = useNavigate();
  const [, setSearchParams] = useSearchParams();
  const [selectedRange, setSelectedRange] = useState(range);
  const [search, setSearch] = useState("");
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(15);

  const fmt = (n: number) =>
    new Intl.NumberFormat("en-US", { style: "currency", currency: currencyCode }).format(n);

  const fmtDate = (d: string | Date) => {
    const date = new Date(d);
    const months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
    return `${date.getDate()} ${months[date.getMonth()]} ${date.getFullYear()}`;
  };

  // CSV date: YYYY-MM-DD — universally recognised by Excel, Numbers, Sheets
  const fmtDateCsv = (d: string | Date) => {
    const date = new Date(d);
    const y = date.getFullYear();
    const m = String(date.getMonth() + 1).padStart(2, "0");
    const day = String(date.getDate()).padStart(2, "0");
    return `${y}-${m}-${day}`;
  };

  const filtered = useMemo(() => {
    setPage(1); // reset to first page on search change
    return rows.filter((r: any) =>
      !search ||
      r.title.toLowerCase().includes(search.toLowerCase()) ||
      r.sku.toLowerCase().includes(search.toLowerCase()) ||
      r.productId.includes(search)
    );
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [rows, search]);

  const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
  const paginated  = filtered.slice((page - 1) * pageSize, page * pageSize);

  const tableRows = paginated.map((r: any) => [
    // Date
    <span style={{ whiteSpace: "nowrap", fontSize: 13 }}>{fmtDate(r.runDate)}</span>,
    // Product ID
    <span style={{ fontFamily: "monospace", fontSize: 12, opacity: 0.7 }}>{r.productId}</span>,
    // SKU
    <span style={{ fontSize: 13 }}>{r.sku || "—"}</span>,
    // Title
    <span style={{ fontSize: 13, fontWeight: 500 }}>{r.title}</span>,
    // Original price
    <span style={{ fontSize: 13 }}>{fmt(r.originalPrice)}</span>,
    // Discount
    <Badge tone={r.discountType === "percentage" ? "attention" : "info"}>
      {r.discountLabel} off
    </Badge>,
    // Units sold
    <span style={{ fontSize: 13, fontWeight: 600 }}>{r.unitsSold}</span>,
    // Revenue
    <span style={{ fontSize: 13, fontWeight: 600, color: "#008060" }}>{fmt(r.revenue)}</span>,
  ]);

  const handleExport = () => {
    const header = "Date,Product ID,SKU,Title,Original Price,Discount (%),Units Sold,Revenue\n";
    const csv = filtered
      .map((r: any) =>
        [
          fmtDateCsv(r.runDate),           // YYYY-MM-DD — Excel recognises this natively
          r.productId,
          r.sku || "",
          `"${r.title.replace(/"/g, '""')}"`,
          r.originalPrice.toFixed(2),
          r.discountLabel,
          r.unitsSold,
          r.revenue.toFixed(2),
        ].join(",")
      )
      .join("\n");
    // UTF-8 BOM (﻿) tells Excel to open with correct encoding
    const blob = new Blob(["﻿" + header + csv], { type: "text/csv;charset=utf-8;" });
    const url  = URL.createObjectURL(blob);
    const a    = document.createElement("a");
    a.href     = url;
    a.download = `deal-history-${selectedRange}.csv`;
    a.click();
  };

  const pagerBtn = (disabled: boolean, active = false): React.CSSProperties => ({
    padding:         "6px 12px",
    border:          active ? "2px solid #008060" : "1px solid #c9cccf",
    borderRadius:    6,
    background:      active ? "#008060" : disabled ? "#f6f6f7" : "#ffffff",
    color:           active ? "#ffffff" : disabled ? "#c9cccf" : "#202223",
    cursor:          disabled ? "default" : "pointer",
    fontSize:        13,
    fontWeight:      active ? 600 : 400,
    minWidth:        36,
    textAlign:       "center",
  });

  return (
    <Page
      title="Past Deals"
      subtitle="Performance results for all completed deals"
      backAction={{ content: "Dashboard", onAction: () => navigate("/app") }}
      primaryAction={{ content: "Export CSV", onAction: handleExport }}
    >
      <BlockStack gap="500">

        {/* ── Summary cards ── */}
        <InlineGrid columns={4} gap="400">
          <Card>
            <BlockStack gap="100">
              <Text as="p" tone="subdued" variant="bodyMd">Deals Run</Text>
              <Text as="p" variant="headingXl">{summary.dealsRun}</Text>
            </BlockStack>
          </Card>
          <Card>
            <BlockStack gap="100">
              <Text as="p" tone="subdued" variant="bodyMd">Units Sold</Text>
              <Text as="p" variant="headingXl">{summary.unitsSold}</Text>
            </BlockStack>
          </Card>
          <Card>
            <BlockStack gap="100">
              <Text as="p" tone="subdued" variant="bodyMd">Revenue</Text>
              <Text as="p" variant="headingXl">{fmt(summary.revenue)}</Text>
            </BlockStack>
          </Card>
          <Card>
            <BlockStack gap="100">
              <Text as="p" tone="subdued" variant="bodyMd">Widget Views</Text>
              <Text as="p" variant="headingXl">{summary.impressions}</Text>
            </BlockStack>
          </Card>
        </InlineGrid>

        {/* ── Filters ── */}
        <InlineStack gap="400" align="start" blockAlign="end">
          <div style={{ minWidth: 180 }}>
            <Select
              label="Time range"
              options={[
                { label: "Last 7 days",  value: "week"  },
                { label: "Last 30 days", value: "month" },
                { label: "Last year",    value: "year"  },
                { label: "All time",     value: "all"   },
              ]}
              value={selectedRange}
              onChange={(v) => {
                setSelectedRange(v);
                setSearchParams({ range: v });
              }}
            />
          </div>
          <div style={{ flex: 1, maxWidth: 320 }}>
            <label style={{ display: "block", fontSize: 14, fontWeight: 500, marginBottom: 4 }}>
              Search
            </label>
            <input
              type="text"
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              placeholder="Filter by title, SKU or product ID…"
              style={{
                width:        "100%",
                padding:      "8px 12px",
                border:       "1px solid #c9cccf",
                borderRadius: 8,
                fontSize:     14,
                outline:      "none",
                boxSizing:    "border-box",
              }}
            />
          </div>
          <div style={{ minWidth: 130 }}>
            <Select
              label="Per page"
              options={[
                { label: "10 per page",  value: "10"  },
                { label: "15 per page",  value: "15"  },
                { label: "25 per page",  value: "25"  },
                { label: "50 per page",  value: "50"  },
              ]}
              value={String(pageSize)}
              onChange={(v) => { setPageSize(Number(v)); setPage(1); }}
            />
          </div>
          <div style={{ paddingTop: 22, fontSize: 13, color: "#6d7175" }}>
            {filtered.length} deal{filtered.length !== 1 ? "s" : ""}
            {totalPages > 1 && ` · page ${page} of ${totalPages}`}
          </div>
        </InlineStack>

        {/* ── Main table ── */}
        <Card padding="0">
          {filtered.length === 0 ? (
            <Box padding="800">
              <BlockStack gap="200" align="center">
                <Text as="p" tone="subdued" alignment="center" variant="bodyLg">
                  No deals found for the selected period.
                </Text>
                <Text as="p" tone="subdued" alignment="center" variant="bodySm">
                  Try selecting a wider time range or clearing the search filter.
                </Text>
              </BlockStack>
            </Box>
          ) : (
            <DataTable
              columnContentTypes={["text","text","text","text","numeric","text","numeric","numeric"]}
              headings={["Date", "Product ID", "SKU", "Title", "Orig. Price", "Discount", "Units Sold", "Revenue"]}
              rows={tableRows}
              totals={[
                "", "", "", "",
                "",
                "",
                filtered.reduce((s: number, r: any) => s + r.unitsSold, 0),
                fmt(filtered.reduce((s: number, r: any) => s + r.revenue, 0)),
              ]}
              showTotalsInFooter
              defaultSortDirection="descending"
              initialSortColumnIndex={6}
            />
          )}
        </Card>

        {/* ── Pagination ── */}
        {totalPages > 1 && (
          <div style={{ display: "flex", justifyContent: "center", alignItems: "center", gap: 8, paddingBottom: 8 }}>
            <button
              onClick={() => setPage(1)}
              disabled={page === 1}
              style={pagerBtn(page === 1)}
              title="First page"
            >«</button>
            <button
              onClick={() => setPage((p) => Math.max(1, p - 1))}
              disabled={page === 1}
              style={pagerBtn(page === 1)}
            >‹ Prev</button>

            {/* Page number pills */}
            {Array.from({ length: totalPages }, (_, i) => i + 1)
              .filter((p) => p === 1 || p === totalPages || Math.abs(p - page) <= 2)
              .reduce<(number | "…")[]>((acc, p, i, arr) => {
                if (i > 0 && (p as number) - (arr[i - 1] as number) > 1) acc.push("…");
                acc.push(p);
                return acc;
              }, [])
              .map((p, i) =>
                p === "…" ? (
                  <span key={`ellipsis-${i}`} style={{ padding: "0 4px", color: "#6d7175" }}>…</span>
                ) : (
                  <button
                    key={p}
                    onClick={() => setPage(p as number)}
                    style={pagerBtn(false, p === page)}
                  >{p}</button>
                )
              )}

            <button
              onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
              disabled={page === totalPages}
              style={pagerBtn(page === totalPages)}
            >Next ›</button>
            <button
              onClick={() => setPage(totalPages)}
              disabled={page === totalPages}
              style={pagerBtn(page === totalPages)}
              title="Last page"
            >»</button>
          </div>
        )}

      </BlockStack>
    </Page>
  );
}
