"use client";

import { useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { CheckCircle2, X } from "lucide-react";
import { Toast as ToastPrimitive } from "radix-ui";
import { PageHeader } from "@/components/shared/page";
import { DataTable } from "@/components/shared/data-table";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import {
  usePreviewRole,
  PreviewLink,
} from "@/components/layout/preview-context";
import { canManage, isManager } from "@/lib/preview";
import { useLocations } from "./store";
import { resolveLocationTab, scopedLocations } from "./model";
import type {
  CreateLocationPayload,
  LocationDirectoryRecord,
  UpdateLocationPayload,
} from "./api-contract";
import type { LocationDirectoryPageData } from "./location-server";
import type { GoogleMapConfig } from "./location-map-model";
import { LocationForm } from "./location-form";
import { LocationListTable } from "./location-list-table";
import { LocationMap } from "./location-map";
import { InvestorLocationReport } from "./financial-report";

type LocationPayload = CreateLocationPayload | UpdateLocationPayload;

function getApiError(payload: unknown, fallback: string) {
  if (
    typeof payload === "object" &&
    payload !== null &&
    "error" in payload &&
    typeof payload.error === "string"
  ) {
    return payload.error;
  }
  return fallback;
}

export function LocationDirectory({
  data,
  mapConfig,
}: {
  data: LocationDirectoryPageData;
  mapConfig: GoogleMapConfig | null;
}) {
  const role = usePreviewRole();
  const params = useSearchParams();
  const router = useRouter();
  const { locations: previewLocations } = useLocations();
  const [editing, setEditing] = useState<LocationDirectoryRecord | null>(null);
  const [formOpen, setFormOpen] = useState(false);
  const [deleting, setDeleting] = useState<LocationDirectoryRecord | null>(null);
  const [selected, setSelected] = useState("");
  const [notice, setNotice] = useState("");
  const [deleteError, setDeleteError] = useState("");
  const [deletingNow, setDeletingNow] = useState(false);
  const rows = scopedLocations(previewLocations, role);
  const manager = isManager(role);
  const manage = canManage(role);
  const tab = resolveLocationTab(params.get("tab"));
  const map = tab === "map";


  function setLocationTab(value: string) {
    const query = new URLSearchParams(window.location.search);
    query.set("tab", value);
    query.delete("paginate_page");
    query.delete("query");
    const search = query.toString();
    window.history.replaceState(
      null,
      "",
      `${window.location.pathname}${search ? `?${search}` : ""}`,
    );
  }

  async function saveLocation(payload: LocationPayload): Promise<string | null> {
    const isUpdate = editing !== null;
    let response: Response;
    try {
      response = await fetch(
        isUpdate
          ? `/api/locations/${encodeURIComponent(editing.id)}`
          : "/api/locations",
        {
          method: isUpdate ? "PATCH" : "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify(payload),
        },
      );
    } catch {
      return "The location service could not be reached. Please try again.";
    }
    const result: unknown = await response.json().catch(() => null);
    if (!response.ok) return getApiError(result, "Location could not be saved. Please try again.");
    setFormOpen(false);
    setEditing(null);
    setNotice(isUpdate ? "Location updated successfully." : "Location created successfully.");
    router.refresh();
    return null;
  }

  async function deleteLocation() {
    if (!deleting) return;
    setDeleteError("");
    setDeletingNow(true);
    try {
      const response = await fetch(`/api/locations/${encodeURIComponent(deleting.id)}`, {
        method: "DELETE",
      });
      const result: unknown = await response.json().catch(() => null);
      if (!response.ok) {
        setDeleteError(getApiError(result, "Location could not be deleted. Please try again."));
        return;
      }
      setDeleting(null);
      setNotice("Location deleted successfully.");
      router.refresh();
    } catch {
      setDeleteError("The location service could not be reached. Please try again.");
    } finally {
      setDeletingNow(false);
    }
  }

  return (
    <ToastPrimitive.Provider duration={4000} swipeDirection="right">
      <div className="space-y-5">
        <PageHeader title={role === "investor" ? "Financial Report" : "Locations"} />
        {role === "investor" ? (
          <InvestorLocationReport />
        ) : manager ? (
          <DataTable
            title="Assigned Locations"
            description="Location assignment is enforced for this preview role."
            rows={rows}
            columns={[
              {
                key: "name",
                label: "Name",
                render: (row) => (
                  <PreviewLink className="text-primary" href={`/locations/${row.id}`}>
                    {row.name}
                  </PreviewLink>
                ),
              },
              { key: "street", label: "Address" },
              { key: "city", label: "City" },
            ]}
            actions={(row) => (
              <PreviewLink className="text-primary" href={`/locations/${row.id}`}>
                View Sessions
              </PreviewLink>
            )}
          />
        ) : (
          <>
            <nav
              aria-label="Location views"
              className="mb-4 flex max-w-full gap-1 overflow-x-auto border-b"
            >
              {[
                { value: "list", label: "List" },
                { value: "map", label: "Map" },
              ].map((item) => (
                <button
                  key={item.value}
                  type="button"
                  aria-current={tab === item.value ? "page" : undefined}
                  className={
                    "shrink-0 border-b-2 px-4 py-3 text-sm font-medium transition-colors " +
                    (tab === item.value
                      ? "border-primary text-primary"
                      : "border-transparent text-muted-foreground hover:text-foreground")
                  }
                  onClick={() => setLocationTab(item.value)}
                >
                  {item.label}
                </button>
              ))}
            </nav>
            {data.error && (
              <section className="panel flex flex-col items-start gap-3 p-5 sm:flex-row sm:items-center sm:justify-between">
                <div role="alert">
                  <h2 className="font-semibold">Locations are unavailable</h2>
                  <p className="mt-1 max-w-2xl text-sm text-muted-foreground">{data.error}</p>
                </div>
                <Button variant="outline" onClick={() => router.refresh()}>
                  Try again
                </Button>
              </section>
            )}
            {map ? (
              <LocationMap
                rows={data.locations}
                selectedId={selected}
                onSelect={setSelected}
                mapConfig={mapConfig}
              />
            ) : (
              <LocationListTable
                rows={data.locations}
                onCreate={manage ? () => { setEditing(null); setFormOpen(true); } : undefined}
                onEdit={manage ? (row) => { setEditing(row); setFormOpen(true); } : undefined}
                onDelete={manage ? (row) => { setDeleteError(""); setDeleting(row); } : undefined}
                onLocate={(row) => {
                  setSelected(row.id);
                  setLocationTab("map");
                }}
                onRefresh={() => router.refresh()}
              />
            )}
          </>
        )}
        {formOpen && (
          <LocationForm
            key={editing?.id ?? "new"}
            record={editing}
            onClose={() => { setFormOpen(false); setEditing(null); }}
            onSave={saveLocation}
          />
        )}
        <Dialog
          open={!!deleting}
          onOpenChange={(open) => {
            if (!open && !deletingNow) setDeleting(null);
          }}
        >
          <DialogContent>
            <DialogHeader>
              <DialogTitle>Delete location?</DialogTitle>
              <DialogDescription>
                This removes {deleting?.name} from the TIAR location directory.
              </DialogDescription>
            </DialogHeader>
            {deleteError && (
              <p role="alert" className="rounded-md border border-destructive/30 bg-destructive/5 p-3 text-sm text-destructive">
                {deleteError}
              </p>
            )}
            <DialogFooter>
              <Button variant="outline" onClick={() => setDeleting(null)} disabled={deletingNow}>
                Cancel
              </Button>
              <Button variant="destructive" onClick={deleteLocation} disabled={deletingNow}>
                {deletingNow ? "Deleting…" : "Delete location"}
              </Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>
      </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>
  );
}
