"use client";
import { useState, type ReactNode } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import {
  Calculator,
  Plus,
  ArrowUpRight,
  Wallet,
  Landmark,
} from "lucide-react";
import {
  PageHeader,
  Panel,
  Metric,
  StatusBadge,
} from "@/components/shared/page";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
} from "@/components/ui/dialog";
import type { SectionData } from "./server";
import {
  isRecord,
  numeric,
  text,
  unwrap,
  parseFinancialRecord,
  type FinancialRecord,
  type FinancialChargepoints,
} from "./contract";
import { currencyTotals, date, money, recovery } from "./display";
import {
  financialFetch,
  FinancialFormDialog,
  type FinancialDialog,
} from "./dialog";
function DataTable({
  headers,
  children,
}: {
  headers: string[];
  children: ReactNode;
}) {
  return (
    <div className="overflow-x-auto">
      <table className="w-full whitespace-nowrap text-left text-sm">
        <thead className="bg-muted/40 text-xs text-muted-foreground">
          <tr>
            {headers.map((header) => (
              <th key={header} className="px-5 py-3 font-medium">
                {header}
              </th>
            ))}
          </tr>
        </thead>
        <tbody className="divide-y">{children}</tbody>
      </table>
    </div>
  );
}
const cell = "px-5 py-4 align-middle";
function Section({
  title,
  description,
  state,
  pageKey,
  children,
  actions,
}: {
  title: string;
  description: string;
  state: SectionData;
  pageKey: string;
  children: ReactNode;
  actions?: ReactNode;
}) {
  const params = useSearchParams(),
    router = useRouter();
  function navigate(page: number) {
    const query = new URLSearchParams(params);
    query.set(pageKey, String(page));
    router.push(`?${query}`, { scroll: false });
  }
  return (
    <Panel>
      <div className="flex flex-wrap items-center justify-between gap-4 border-b p-5">
        <div>
          <h2 className="font-semibold">{title}</h2>
          <p className="mt-1 text-sm text-muted-foreground">{description}</p>
        </div>
        {actions}
      </div>
      {state.error ? (
        <div className="flex flex-wrap items-center justify-between gap-3 p-5">
          <p role="alert" className="text-sm text-destructive">
            {state.error}
          </p>
          <Button variant="outline" onClick={() => router.refresh()}>
            Retry
          </Button>
        </div>
      ) : state.data?.rows.length ? (
        children
      ) : (
        <p className="p-10 text-center text-sm text-muted-foreground">
          No {title.toLowerCase()} found.
        </p>
      )}
      {state.data && state.data.pages !== null && state.data.pages > 1 && (
        <div className="flex items-center justify-between gap-3 border-t px-5 py-3 text-xs text-muted-foreground">
          <span>{`Page ${state.data.page} of ${state.data.pages}`}</span>
          {state.data.pages !== null && state.data.pages > 1 && (
            <div className="flex gap-2">
              <Button
                variant="outline"
                size="sm"
                disabled={state.data.page <= 1}
                onClick={() => navigate((state.data?.page ?? 1) - 1)}
              >
                Previous
              </Button>
              <Button
                variant="outline"
                size="sm"
                disabled={state.data.page >= state.data.pages}
                onClick={() => navigate((state.data?.page ?? 1) + 1)}
              >
                Next
              </Button>
            </div>
          )}
        </div>
      )}
    </Panel>
  );
}
function Recovery({ row }: { row: FinancialRecord }) {
  const percent = recovery(row);
  return (
    <div className="min-w-36">
      <div className="mb-2 flex justify-between gap-5 text-xs">
        <span>Capital recovered</span>
        <span className="font-medium tabular-nums">
          {percent === null ? "—" : `${percent.toFixed(1)}%`}
        </span>
      </div>
      <progress
        aria-label={`Capital recovered for investment ${row.id}`}
        value={Math.min(100, Math.max(0, percent ?? 0))}
        max={100}
        className="h-2 w-full overflow-hidden rounded-full accent-primary"
      />
    </div>
  );
}
export function FinancialDashboard({
  revenue,
  investments,
  settlements,
  chargepoints,
  investors,
  locations,
}: {
  locations: FinancialChargepoints;
  investors: FinancialChargepoints;
  chargepoints: FinancialChargepoints;
  revenue: SectionData;
  investments: SectionData;
  settlements: SectionData;
}) {
  const revenueById = new Map(
    revenue.data?.rows.map((row) => [row.id, row]) ?? [],
  );
  const chargepointNames = new Map(
    chargepoints.options.map((option) => [
      option.value,
      option.name ?? option.label,
    ]),
  );
  const locationNames = new Map(
    locations.options.map((option) => [
      option.value,
      option.name ?? option.label,
    ]),
  );
  const investorNames = new Map(
    investors.options.map((option) => [
      option.value,
      option.name ?? option.label,
    ]),
  );
  const chargepointLocations = new Map(
    chargepoints.options.map((option) => [option.value, option.locationId]),
  );
  function chargepointLabel(row: Record<string, unknown>) {
    return (
      text(row, "charge_point_name") ||
      chargepointNames.get(text(row, "charge_point_id")) ||
      "Chargepoint name unavailable"
    );
  }
  function locationLabel(row: Record<string, unknown>) {
    const id =
      text(row, "location_id") ||
      chargepointLocations.get(text(row, "charge_point_id"));
    return (
      text(row, "location_name") ||
      (id ? locationNames.get(id) : undefined) ||
      "Location name unavailable"
    );
  }
  function recipientLabel(row: Record<string, unknown>) {
    return (
      text(row, "recipient_name") ||
      text(row, "investor_name") ||
      investorNames.get(
        text(row, "investor_user_id") || text(row, "recipient_id"),
      ) ||
      (row.recipient_type === "platform"
        ? "Platform"
        : "Recipient name unavailable")
    );
  }
  const [dialog, setDialog] = useState<FinancialDialog | null>(null);
  const [detail, setDetail] = useState<FinancialRecord | null>(null),
    [detailError, setDetailError] = useState(""),
    [loadingDetail, setLoadingDetail] = useState(false),
    [detailOpen, setDetailOpen] = useState(false);
  async function showSettlement(row: FinancialRecord) {
    setDetailOpen(true);
    setDetail(null);
    setDetailError("");
    setLoadingDetail(true);
    try {
      setDetail(
        parseFinancialRecord(
          unwrap(await financialFetch(`payout-settlements/${row.id}`)),
        ),
      );
    } catch (error) {
      setDetailError(
        error instanceof Error
          ? error.message
          : "Unable to load settlement details.",
      );
    } finally {
      setLoadingDetail(false);
    }
  }
  return (
    <div className="min-w-0 max-w-full overflow-hidden">
      <PageHeader title="Return on Investment (ROI)" />
      <div className="space-y-6">
        <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
          <Metric
            label="Gross revenue"
            value={currencyTotals(revenue.data?.rows ?? [], "gross_amount")}
            note="Revenue records returned by the API"
          />
          <Metric
            label="Net revenue"
            value={currencyTotals(revenue.data?.rows ?? [], "net_revenue")}
            note="After electricity costs and platform fees"
          />
          <Metric
            label="Invested capital"
            value={currencyTotals(
              investments.data?.rows ?? [],
              "investment_amount",
            )}
            note="Investment records returned by the API"
          />
          <Metric
            label="Settlements recorded as paid"
            value={currencyTotals(
              (settlements.data?.rows ?? []).filter(
                (row) => row.status === "paid",
              ),
              "total_amount",
            )}
            note="Status recorded in the financial service"
          />
        </div>
        <Section
          title="Revenue shares"
          description="Session revenue, operating costs, and recipient allocations."
          state={revenue}
          pageKey="revenue_page"
          actions={
            <div className="flex flex-wrap gap-2">
              <Button
                variant="outline"
                onClick={() => setDialog({ action: "estimate" })}
              >
                <Calculator className="size-4" aria-hidden="true" />
                Estimate investment
              </Button>
              <Button
                onClick={() => setDialog({ action: "create-investment" })}
              >
                <Plus className="size-4" aria-hidden="true" />
                Create investment
              </Button>
            </div>
          }
        >
          <DataTable
            headers={[
              "Chargepoint / location",
              "Billing period",
              "Gross",
              "Electricity cost",
              "Platform fee",
              "Net revenue",
              "Status",
              "Allocation",
            ]}
          >
            {revenue.data?.rows.map((row) => (
              <tr key={row.id} className="hover:bg-muted/20">
                <td className={cell}>
                  <span className="block font-medium">
                    {chargepointLabel(row)}
                  </span>
                  <span className="block text-xs text-muted-foreground">
                    {locationLabel(row)}
                  </span>
                </td>
                <td className={cell}>{date(row.billing_period)}</td>
                {[
                  "gross_amount",
                  "electricity_cost",
                  "platform_fee",
                  "net_revenue",
                ].map((key) => (
                  <td
                    key={key}
                    className={`${cell} tabular-nums ${key === "net_revenue" ? "font-semibold text-primary" : ""}`}
                  >
                    {money(row[key], row.currency)}
                  </td>
                ))}
                <td className={cell}>
                  <StatusBadge>{text(row, "status") || "Unknown"}</StatusBadge>
                </td>
                <td className={cell}>
                  <details>
                    <summary className="cursor-pointer text-primary">
                      View allocation
                    </summary>
                    <ul className="mt-3 space-y-2">
                      {Array.isArray(row.items) &&
                        row.items.filter(isRecord).map((item, index) => (
                          <li
                            key={typeof item.id === "string" ? item.id : index}
                            className="text-xs"
                          >
                            <span className="capitalize">
                              {text(item, "recipient_type").replaceAll(
                                "_",
                                " ",
                              )}
                            </span>{" "}
                            · {numeric(item.percentage) ?? "—"}% ·{" "}
                            {money(item.amount, row.currency)}
                            {typeof item.recipient_id === "string" && (
                              <span className="block text-muted-foreground">
                                {recipientLabel(item)}
                              </span>
                            )}
                          </li>
                        ))}
                    </ul>
                  </details>
                </td>
              </tr>
            ))}
          </DataTable>
        </Section>
        <Section
          title="Investor investments"
          description="Track investment terms, earned revenue, and progress toward break-even."
          state={investments}
          pageKey="investment_page"
          actions={
            <Landmark
              className="size-5 text-muted-foreground"
              aria-hidden="true"
            />
          }
        >
          <DataTable
            headers={[
              "Investor / chargepoint",
              "Investment",
              "Ownership",
              "Expected / month",
              "Revenue to date",
              "Recovery",
              "Target BEP",
              "Status",
              "Actions",
            ]}
          >
            {investments.data?.rows.map((row) => (
              <tr key={row.id} className="hover:bg-muted/20">
                <td className={cell}>
                  <span className="block font-medium">
                    {recipientLabel(row)}
                  </span>
                  <span className="block text-xs">{chargepointLabel(row)}</span>
                  <span className="block text-xs text-muted-foreground">
                    {locationLabel(row)}
                  </span>
                  <span className="mt-1 block text-xs text-muted-foreground">
                    Since {date(row.started_at)}
                  </span>
                </td>
                <td className={`${cell} font-semibold tabular-nums`}>
                  {money(row.investment_amount, row.currency)}
                </td>
                <td className={cell}>
                  {numeric(row.ownership_percentage) ?? "—"}%
                </td>
                <td className={cell}>
                  {money(row.expected_monthly_revenue, row.currency)}
                </td>
                <td className={cell}>
                  {money(row.actual_revenue_to_date, row.currency)}
                </td>
                <td className={cell}>
                  <Recovery row={row} />
                </td>
                <td className={cell}>
                  {numeric(row.target_bep_months) ?? "—"} months
                </td>
                <td className={cell}>
                  <StatusBadge>
                    {row.active === true ? "Active" : "Inactive"}
                  </StatusBadge>
                </td>
                <td className={cell}>
                  <Button
                    size="sm"
                    variant="outline"
                    onClick={() =>
                      setDialog({ action: "update-investment", row })
                    }
                  >
                    Edit
                  </Button>
                </td>
              </tr>
            ))}
          </DataTable>
        </Section>
        <Section
          title="Payout settlements"
          description="Review settlement items and update their recorded payment status."
          state={settlements}
          pageKey="settlement_page"
          actions={
            <Wallet
              className="size-5 text-muted-foreground"
              aria-hidden="true"
            />
          }
        >
          <DataTable
            headers={[
              "Recipient",
              "Settlement period",
              "Amount",
              "Status",
              "Payment reference",
              "Paid at",
              "Actions",
            ]}
          >
            {settlements.data?.rows.map((row) => (
              <tr key={row.id} className="hover:bg-muted/20">
                <td className={cell}>
                  <span className="capitalize">
                    {text(row, "recipient_type").replaceAll("_", " ")}
                  </span>
                  <span className="block font-medium">
                    {recipientLabel(row)}
                  </span>
                </td>
                <td className={cell}>
                  {date(row.settlement_period)}
                  <span className="block text-xs capitalize text-muted-foreground">
                    {text(row, "period_type")}
                  </span>
                </td>
                <td className={`${cell} font-semibold tabular-nums`}>
                  {money(row.total_amount, row.currency)}
                </td>
                <td className={cell}>
                  <StatusBadge>{text(row, "status") || "Unknown"}</StatusBadge>
                </td>
                <td className={cell}>
                  {text(row, "payment_reference") || "—"}
                </td>
                <td className={cell}>{date(row.paid_at)}</td>
                <td className={cell}>
                  <div className="flex gap-2">
                    <Button
                      size="sm"
                      variant="outline"
                      onClick={() => void showSettlement(row)}
                    >
                      Details
                      <ArrowUpRight className="size-3" aria-hidden="true" />
                    </Button>
                    <Button
                      size="sm"
                      variant="outline"
                      onClick={() =>
                        setDialog({ action: "update-settlement", row })
                      }
                    >
                      Edit status
                    </Button>
                  </div>
                </td>
              </tr>
            ))}
          </DataTable>
        </Section>
      </div>
      {dialog && (
        <FinancialFormDialog
          key={`${dialog.action}-${dialog.row?.id ?? "new"}`}
          dialog={dialog}
          chargepoints={chargepoints}
          investors={investors}
          close={() => setDialog(null)}
          createFromEstimate={(seed) =>
            setDialog({ action: "create-investment", seed })
          }
        />
      )}
      <Dialog open={detailOpen} onOpenChange={setDetailOpen}>
        <DialogContent className="max-h-[85dvh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Settlement details</DialogTitle>
            <DialogDescription>
              Revenue share items included in this payout settlement.
            </DialogDescription>
          </DialogHeader>
          {loadingDetail ? (
            <p role="status">Loading settlement…</p>
          ) : detailError ? (
            <p role="alert" className="text-destructive">
              {detailError}
            </p>
          ) : (
            detail && (
              <div className="space-y-4">
                <p className="text-2xl font-semibold">
                  {money(detail.total_amount, detail.currency)}
                </p>
                <p className="font-medium">{recipientLabel(detail)}</p>
                <p className="text-sm text-muted-foreground">
                  {text(detail, "notes") || "No notes"}
                </p>
                <DataTable headers={["Revenue source", "Amount", "Status"]}>
                  {Array.isArray(detail.items) &&
                    detail.items.filter(isRecord).map((item, index) => (
                      <tr key={typeof item.id === "string" ? item.id : index}>
                        <td className={cell}>
                          {(() => {
                            const share = revenueById.get(
                              String(item.revenue_share_id),
                            );
                            return share ? (
                              <>
                                <span className="block">
                                  {chargepointLabel(share)}
                                </span>
                                <span className="text-xs text-muted-foreground">
                                  {date(share.billing_period)}
                                </span>
                              </>
                            ) : (
                              <span>Revenue allocation {index + 1}</span>
                            );
                          })()}
                        </td>
                        <td className={cell}>
                          {money(item.amount, detail.currency)}
                        </td>
                        <td className={cell}>
                          <StatusBadge>{text(item, "status")}</StatusBadge>
                        </td>
                      </tr>
                    ))}
                </DataTable>
              </div>
            )
          )}
        </DialogContent>
      </Dialog>
    </div>
  );
}
