"use client";
import { useState } from "react";
import { CheckCircle2, X } from "lucide-react";
import { Toast as ToastPrimitive } from "radix-ui";
import { useRouter, useSearchParams } from "next/navigation";
import { DataTable } from "@/components/shared/data-table";
import { recentDateTime } from "@/lib/format";
import { Button } from "@/components/ui/button";
import { StatusBadge } from "@/components/shared/page";
import { Tabs, useQueryUpdate } from "@/components/shared/tabs";
import { usePreviewRole } from "@/components/layout/preview-context";
import { canManage } from "@/lib/preview";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { RateSchedules, ScheduleAssignmentsList } from "./rate-schedules";
import { AssignTariffDialog, CreateTariffDialog } from "./tariff-dialogs";
import { submitPricingMutation } from "./pricing-client";
import type {
  PricingCatalog,
  PricingDetail,
  PricingListState,
  TariffAssignment,
  TariffListItem,
  TariffSummary,
} from "./api-contract";
import { groupTariffPriceComponents } from "./pricing-view";

const tabs = [
  { value: "base", label: "Base pricing" },
  { value: "schedule", label: "Schedules" },
];
const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

type TariffRow = TariffListItem & {
  status: "Active" | "Inactive";
  component_search: string;
};

function formatAmount(amount: number, currency: string) {
  try {
    return new Intl.NumberFormat("id-ID", {
      style: "currency",
      currency,
      maximumFractionDigits: 2,
    }).format(amount);
  } catch {
    return `${currency} ${amount.toLocaleString("id-ID")}`;
  }
}

function ApiError({ message, onRetry }: { message: string; onRetry: () => void }) {
  return (
    <section className="panel flex flex-col items-start gap-3 p-6 sm:flex-row sm:items-center sm:justify-between">
      <div role="alert">
        <h2 className="font-semibold">Pricing data is unavailable</h2>
        <p className="mt-1 max-w-2xl text-sm text-muted-foreground">{message}</p>
      </div>
      <Button variant="outline" onClick={onRetry}>Try again</Button>
    </section>
  );
}

function DetailDialog({
  open,
  detail,
  error,
  catalog,
  onClose,
}: {
  open: boolean;
  detail: PricingDetail | null;
  error: string | null;
  catalog: PricingCatalog;
  onClose: () => void;
}) {
  const title =
    detail?.kind === "schedule"
      ? detail.data.name
      : detail?.kind === "target"
        ? "Schedule target"
        : "Pricing details";
  const scheduleAssignments =
    detail?.kind === "schedule"
      ? detail.data.assignments ??
        catalog.schedules.data.find((schedule) => schedule.id === detail.data.id)?.assignments
      : undefined;
  return (
    <Dialog open={open} onOpenChange={(value) => !value && onClose()}>
      <DialogContent className="max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>{title}</DialogTitle>
        </DialogHeader>
        {error ? (
          <p role="alert" className="rounded-md border border-destructive/30 bg-destructive/5 p-3 text-sm text-destructive">
            {error}
          </p>
        ) : detail?.kind === "schedule" ? (
          <div className="space-y-4">
            <dl className="grid gap-3 rounded-lg border bg-muted/20 p-4 sm:grid-cols-2">
              <div><dt className="text-xs text-muted-foreground">Code</dt><dd className="mt-1 font-medium">{detail.data.code}</dd></div>
              <div><dt className="text-xs text-muted-foreground">Commercial model</dt><dd className="mt-1 font-medium">{detail.data.commercial_model}</dd></div>
              <div><dt className="text-xs text-muted-foreground">Default tariff</dt><dd className="mt-1 font-medium">{catalog.tariffs.data.find((item) => item.id === detail.data.default_tariff_id)?.name ?? "Unavailable tariff"}</dd></div>
              <div><dt className="text-xs text-muted-foreground">Timezone</dt><dd className="mt-1 font-medium">{detail.data.timezone}</dd></div>
              <div><dt className="text-xs text-muted-foreground">Status</dt><dd className="mt-1"><StatusBadge>{detail.data.active ? "Active" : "Inactive"}</StatusBadge></dd></div>
              <div><dt className="text-xs text-muted-foreground">Updated</dt><dd className="mt-1 font-medium">{recentDateTime(detail.data.updated_at)}</dd></div>
            </dl>
            {detail.data.description && <p className="text-sm text-muted-foreground">{detail.data.description}</p>}
            <section className="space-y-2">
              <h3 className="font-semibold">Weekly targets</h3>
              {catalog.targets.error ? (
                <p role="alert" className="text-sm text-destructive">{catalog.targets.error}</p>
              ) : catalog.targets.data.filter((target) => target.tariff_schedule_id === detail.data.id).length ? (
                catalog.targets.data.filter((target) => target.tariff_schedule_id === detail.data.id).map((target) => (
                  <div className="flex flex-wrap items-center justify-between gap-2 rounded-md border px-3 py-2 text-sm" key={target.id}>
                    <span>{days[target.day_of_week]} · {target.start_time.slice(0, 5)}–{target.end_time.slice(0, 5)}</span>
                    <span className="text-muted-foreground">{catalog.tariffs.data.find((item) => item.id === target.tariff_id)?.name ?? "Unavailable tariff"}</span>
                  </div>
                ))
              ) : (
                <p className="text-sm text-muted-foreground">No weekly targets are configured.</p>
              )}
            </section>
            <section className="space-y-2">
              <h3 className="font-semibold">Assigned locations and chargers</h3>
              <ScheduleAssignmentsList assignments={scheduleAssignments} />
            </section>
          </div>
        ) : detail?.kind === "target" ? (
          <dl className="grid gap-3 rounded-lg border bg-muted/20 p-4 sm:grid-cols-2">
            <div><dt className="text-xs text-muted-foreground">Schedule</dt><dd className="mt-1 font-medium">{catalog.schedules.data.find((item) => item.id === detail.data.tariff_schedule_id)?.name ?? "Unavailable schedule"}</dd></div>
            <div><dt className="text-xs text-muted-foreground">Tariff</dt><dd className="mt-1 font-medium">{catalog.tariffs.data.find((item) => item.id === detail.data.tariff_id)?.name ?? "Unavailable tariff"}</dd></div>
            <div><dt className="text-xs text-muted-foreground">Day</dt><dd className="mt-1 font-medium">{days[detail.data.day_of_week]}</dd></div>
            <div><dt className="text-xs text-muted-foreground">Time</dt><dd className="mt-1 font-medium">{detail.data.start_time}–{detail.data.end_time}</dd></div>
            <div><dt className="text-xs text-muted-foreground">Status</dt><dd className="mt-1"><StatusBadge>{detail.data.active ? "Active" : "Inactive"}</StatusBadge></dd></div>
          </dl>
        ) : (
          <p className="text-sm text-muted-foreground">Select a pricing record to view its details.</p>
        )}
      </DialogContent>
    </Dialog>
  );
}

function TariffAssignmentsDialog({
  open,
  catalog,
  assignments,
  onClose,
}: {
  open: boolean;
  catalog: PricingCatalog;
  assignments: PricingListState<TariffAssignment>;
  onClose: () => void;
}) {
  return (
    <Dialog open={open} onOpenChange={(value) => !value && onClose()}>
      <DialogContent className="max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>Assigned locations and chargers</DialogTitle>
        </DialogHeader>
        {assignments.error ? (
          <p role="alert" className="rounded-md border border-destructive/30 bg-destructive/5 p-3 text-sm text-destructive">
            {assignments.error}
          </p>
        ) : assignments.data.length ? (
          <div className="space-y-3">
            {assignments.data.map((assignment) => {
              const location = catalog.locations.data.find((item) => item.id === assignment.location_id);
              const chargepoint = catalog.chargepoints.data.find((item) => item.id === assignment.chargepoint_id);
              const connector = catalog.nozzles.data.find((item) => item.id === assignment.connector_id);
              return (
                <article className="rounded-lg border p-4" key={assignment.id}>
                  <dl className="grid gap-3 sm:grid-cols-3">
                    <div className="min-w-0">
                      <dt className="text-xs text-muted-foreground">Charge point</dt>
                      <dd className="mt-1 break-words text-sm font-medium">{chargepoint?.name ?? "Unavailable charge point"}</dd>
                    </div>
                    <div className="min-w-0">
                      <dt className="text-xs text-muted-foreground">Location</dt>
                      <dd className="mt-1 break-words text-sm font-medium">{location?.name ?? "Unavailable location"}</dd>
                    </div>
                    <div className="min-w-0">
                      <dt className="text-xs text-muted-foreground">Connector</dt>
                      <dd className="mt-1 break-words text-sm font-medium">{connector?.name ?? `Connector ${assignment.connector_number}`}</dd>
                    </div>
                  </dl>
                </article>
              );
            })}
          </div>
        ) : (
          <p className="rounded-md border border-dashed px-4 py-5 text-sm text-muted-foreground">
            No locations or chargers are assigned to this tariff.
          </p>
        )}
      </DialogContent>
    </Dialog>
  );
}

export function ChargingPricing({
  data,
}: {
  data: {
    catalog: PricingCatalog;
    detail: PricingDetail | null;
    detailError: string | null;
    assignments: PricingListState<TariffAssignment>;
  };
}) {
  const params = useSearchParams();
  const router = useRouter();
  const updateQuery = useQueryUpdate();
  const manage = canManage(usePreviewRole());
  const tab = params.get("tab") ?? "base";
  const [createOpen, setCreateOpen] = useState(false);
  const [createError, setCreateError] = useState("");
  const [creating, setCreating] = useState(false);
  const [assignmentTariff, setAssignmentTariff] = useState<TariffSummary | null>(null);
  const [assignmentError, setAssignmentError] = useState("");
  const [assigning, setAssigning] = useState(false);
  const [notice, setNotice] = useState("");
  const requestedDetail = Boolean(params.get("schedule") || params.get("target"));
  const requestedAssignments = tab === "base" ? params.get("assignments") : null;
  const tariffsError = data.catalog.tariffs.error;
  const models = Array.from(new Set(data.catalog.tariffs.data.map((item) => item.commercial_model)));
  const rows: TariffRow[] = data.catalog.tariffs.data.map((tariff) => ({
    ...tariff,
    status: tariff.active ? "Active" : "Inactive",
    component_search: tariff.price_components
      .map(({ type, name, unit }) => `${type} ${name} ${unit}`)
      .join(" "),
  }));
  const closeDetail = () => updateQuery({ assignments: null, schedule: null, target: null });

  async function createTariff(payload: Parameters<typeof submitPricingMutation>[2]) {
    setCreating(true);
    setCreateError("");
    const error = await submitPricingMutation("/api/pricing/tariffs", "POST", payload);
    setCreating(false);
    if (error) {
      setCreateError(error);
      return;
    }
    setCreateOpen(false);
    setNotice("Tariff created successfully.");
    router.refresh();
  }

  async function assignTariff(payload: Parameters<typeof submitPricingMutation>[2]) {
    if (!assignmentTariff) return;
    setAssigning(true);
    setAssignmentError("");
    const error = await submitPricingMutation(
      `/api/pricing/tariffs/${encodeURIComponent(assignmentTariff.id)}/assignments`,
      "POST",
      payload,
    );
    setAssigning(false);
    if (error) {
      setAssignmentError(error);
      return;
    }
    setAssignmentTariff(null);
    setNotice("Tariff assignment created successfully.");
    router.refresh();
  }

  return (
    <ToastPrimitive.Provider duration={4000} swipeDirection="right">
      <div className="space-y-5">
        <Tabs
          items={tabs}
          onChange={(value) => updateQuery({
            tab: value,
            assignments: null,
            tariff: null,
            schedule: null,
            target: null,
          })}
        />
        {tab === "schedule" ? (
          <RateSchedules
            catalog={data.catalog}
            manage={manage}
            onOpenDetail={(scheduleId) => updateQuery({ tab: "schedule", schedule: scheduleId, assignments: null, tariff: null, target: null })}
            onOpenTarget={(targetId) => updateQuery({ tab: "schedule", target: targetId, assignments: null, schedule: null, tariff: null })}
            onRefresh={() => router.refresh()}
            onNotice={setNotice}
          />
        ) : tariffsError ? (
          <ApiError message={tariffsError} onRetry={() => router.refresh()} />
        ) : (
          <DataTable
            title="Charging tariffs"
            description="Scroll horizontally to view tariff terms and grouped component prices. Open Assignments to see linked locations and chargers."
            rows={rows}
            searchPlaceholder="Search tariff by name or code..."
            emptyMessage="No tariffs are configured yet. Create a tariff to get started."
            filters={[
              { key: "status", label: "Status", options: ["Active", "Inactive"] },
              ...(models.length ? [{ key: "commercial_model" as const, label: "Commercial model", options: models }] : []),
              ...(rows.length ? [{ key: "currency" as const, label: "Currency", options: Array.from(new Set(rows.map((row) => row.currency))) }] : []),
            ]}
            columns={[
              {
                key: "name",
                label: "Tariff",
                render: (row) => (
                  <div className="min-w-[15rem] max-w-[22rem] space-y-1.5">
                    <p className="font-semibold">{row.name}</p>
                    {row.description && (
                      <p className="text-xs text-muted-foreground">{row.description}</p>
                    )}
                  </div>
                ),
              },
              {
                key: "component_search",
                label: "Price components",
                render: (row) => {
                  const groups = groupTariffPriceComponents(row.price_components);
                  return groups.length ? (
                    <div className="min-w-[32rem] max-w-[40rem] space-y-2.5">
                      {groups.map((group) => (
                        <section className="rounded-lg bg-muted/35 p-2.5" key={group.type}>
                          <p className="mb-2 text-center text-xs font-semibold tracking-wide text-foreground/80">
                            {group.type}
                          </p>
                          <ul aria-label={`${group.type} price components`} className="space-y-2">
                            {group.components.map((component, index) => (
                              <li
                                className="rounded-md border border-border/70 bg-card px-3 py-2.5"
                                key={component.id ?? `${component.type}-${component.name}-${index}`}
                              >
                                <div className="flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1">
                                  <span className="font-medium">{component.name}</span>
                                  <span className="font-semibold">
                                    {formatAmount(component.price, row.currency)}
                                    <span className="font-normal text-muted-foreground">/{component.unit}</span>
                                  </span>
                                </div>
                                <div className="mt-1.5 flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground">
                                  <span>Type: {component.type}</span>
                                  <span>Tax: {component.tax}%</span>
                                  {component.cost_price !== undefined && (
                                    <span>Cost: {formatAmount(component.cost_price, row.currency)}</span>
                                  )}
                                  {component.grace_period !== undefined && (
                                    <span>Grace: {component.grace_period} min</span>
                                  )}
                                  <span>{component.active ? "Active" : "Inactive"}</span>
                                </div>
                              </li>
                            ))}
                          </ul>
                        </section>
                      ))}
                    </div>
                  ) : (
                    <p className="min-w-[32rem] text-sm text-muted-foreground">No price components</p>
                  );
                },
                exportValue: (row) => row.price_components
                  .map((component) => {
                    const extra = [
                      `tax ${component.tax}%`,
                      component.cost_price === undefined
                        ? null
                        : `cost ${formatAmount(component.cost_price, row.currency)}`,
                      component.grace_period === undefined
                        ? null
                        : `grace ${component.grace_period} min`,
                      component.active ? "active" : "inactive",
                    ].filter(Boolean).join("; ");
                    return `${component.type}: ${component.name} — ${formatAmount(component.price, row.currency)} / ${component.unit}; ${extra}`;
                  })
                  .join("\n"),
              },
              { key: "code", label: "Code" },
              { key: "commercial_model", label: "Model" },
              { key: "currency", label: "Currency" },
              { key: "minimum_amount", label: "Minimum amount", render: (row) => formatAmount(row.minimum_amount, row.currency) },
              { key: "status", label: "Status", render: (row) => <StatusBadge>{row.status}</StatusBadge> },
              { key: "updated_at", label: "Updated", render: (row) => recentDateTime(row.updated_at) },
            ]}
            onRefresh={() => router.refresh()}
            onCreate={manage ? () => { setCreateError(""); setCreateOpen(true); } : undefined}
            createLabel="Create tariff"
            actions={(row) => (
              <div className="flex flex-wrap gap-2">
                <Button
                  size="sm"
                  variant="outline"
                  aria-label={`View assignments for ${row.name}`}
                  onClick={() => updateQuery({ tab: "base", assignments: row.id, tariff: null, schedule: null, target: null })}
                >
                  Assignments
                </Button>
                {manage && (
                  <Button
                    size="sm"
                    onClick={() => { setAssignmentError(""); setAssignmentTariff(row); }}
                  >
                    Assign
                  </Button>
                )}
              </div>
            )}
          />
        )}
        {createOpen && (
          <CreateTariffDialog
            commercialModels={models}
            error={createError}
            submitting={creating}
            onClose={() => setCreateOpen(false)}
            onSubmit={createTariff}
          />
        )}
        {assignmentTariff && (
          <AssignTariffDialog
            tariff={assignmentTariff}
            catalog={data.catalog}
            error={assignmentError}
            submitting={assigning}
            onClose={() => setAssignmentTariff(null)}
            onSubmit={assignTariff}
          />
        )}
        <TariffAssignmentsDialog
          open={Boolean(requestedAssignments)}
          catalog={data.catalog}
          assignments={data.assignments}
          onClose={() => updateQuery({ assignments: null })}
        />
        <DetailDialog
          open={requestedDetail}
          detail={data.detail}
          error={data.detailError}
          catalog={data.catalog}
          onClose={closeDetail}
        />
      </div>
      {notice && (
        <ToastPrimitive.Root
          open
          onOpenChange={(open) => !open && setNotice("")}
          className="flex items-center gap-3 rounded-xl border bg-popover p-4 text-popover-foreground shadow-lg data-[state=closed]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-bottom-2 sm:max-w-sm"
        >
          <CheckCircle2 aria-hidden="true" className="size-5 shrink-0 text-success" />
          <ToastPrimitive.Description className="min-w-0 flex-1 text-sm">
            {notice}
          </ToastPrimitive.Description>
          <ToastPrimitive.Close
            type="button"
            aria-label="Dismiss notification"
            className="inline-flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
          >
            <X aria-hidden="true" className="size-4" />
          </ToastPrimitive.Close>
        </ToastPrimitive.Root>
      )}
      <ToastPrimitive.Viewport className="fixed bottom-4 right-4 z-[100] flex w-[calc(100%-2rem)] flex-col gap-2 outline-none sm:max-w-sm" />
    </ToastPrimitive.Provider>
  );
}
