"use client";
import { useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { MoreHorizontal, MapPin, Pencil, Trash } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import { TableToolbar } from "@/components/shared/table-toolbar";
import {
  PaginationControls,
  SortHeading,
} from "@/components/shared/query-controls";
import { EmptyState } from "@/components/shared/panel";
import { saveDraft } from "@/mocks/drafts";
import type { Pagination } from "@/lib/list-query";
import { LocationEditor } from "./location-editor";
import { removeLocation, saveLocation } from "./client-api";
import type { Location, LocationWritePayload } from "./types";

function displayAddress(row: Location) {
  const parts = [row.address];
  const included = new Set(row.address.split(",").map(part => part.trim().toLowerCase()));
  for (const part of [row.city, row.state, row.postalCode]) {
    if (!part || included.has(part.trim().toLowerCase())) continue;
    parts.push(part);
    included.add(part.trim().toLowerCase());
  }
  return parts.filter(Boolean).join(", ");
}

export function LocationTable({
  data,
  pagination,
  source = "preview",
  searchEnabled = true,
  paginationEnabled = true,
  canManage = true,
  loadError,
  loadNotice,
}: {
  data: Location[];
  pagination: Pagination;
  source?: "api" | "preview";
  searchEnabled?: boolean;
  paginationEnabled?: boolean;
  canManage?: boolean;
  loadError?: string;
  loadNotice?: string;
}) {
  const router = useRouter();
  const [rowState, setRowState] = useState(() => ({ source: data, rows: data }));
  const rows = rowState.source === data ? rowState.rows : data;
  function setRows(update: Location[] | ((current: Location[]) => Location[])) {
    setRowState((current) => {
      const currentRows = current.source === data ? current.rows : data;
      return {
        source: data,
        rows:
          typeof update === "function" ? update(currentRows) : update,
      };
    });
  }
  const [editor, setEditor] = useState(false);
  const [editing, setEditing] = useState<Location>();
  const [deleting, setDeleting] = useState<Location>();
  const [notice, setNotice] = useState("");
  const [error, setError] = useState("");
  const [isDeleting, setIsDeleting] = useState(false);
  const visibleError = error || loadError;
  return (
    <section className="panel overflow-hidden">
      <TableToolbar
        title="Locations"
        description="Manage and monitor charging locations"
        searchKey="name"
        fields={[]}
        showFilters={false}
        showSearch={searchEnabled}
        searchDebounceMs={300}
        refreshNotice="Locations refreshed"
        exportIds={rows.map((row) => row.id)}
        exportRows={rows.map((row) => ({
          Name: row.name,
          Address: row.address,
          Code: row.code ?? "",
          Email: row.email,
          Phone: row.phone,
          Latitude: row.latitude,
          Longitude: row.longitude,
        }))}
        onCreate={canManage ? () => {
          setEditing(undefined);
          setEditor(true);
        } : undefined}
      />
      {visibleError && (
        <p role="alert" className="px-5 pb-3 text-destructive">
          {visibleError}
        </p>
      )}
      {loadNotice && (
        <p role="status" className="px-5 pb-3 text-sm text-muted-foreground">
          {loadNotice}
        </p>
      )}
      {notice && (
        <p role="status" className="px-5 pb-3 text-muted-foreground">
          {notice}
        </p>
      )}
      <div className="overflow-x-auto">
        <table className="data-table min-w-[1000px]">
          <caption className="sr-only">Charging locations</caption>
          <thead>
            <tr>
              {[
                ["Location Name", "name"],
                ["Address", "address"],
                ["Code", "code"],
                ["Email", "email"],
                ["Phone", "phone"],
                ["Coordinates", "latitude"],
              ].map(([label, key]) => (
                <SortHeading key={key} label={label} value={key} />
              ))}
              <th>Actions</th>
            </tr>
          </thead>
          <tbody>
            {rows.map((row) => (
              <tr key={row.id}>
                <td className="min-w-48 font-medium">
                  <Link href={`/locations/${row.id}`}>{row.name}</Link>
                </td>
                <td className="max-w-60">
                  {displayAddress(row)}
                </td>
                <td>{row.code || "-"}</td>
                <td>{row.email || "-"}</td>
                <td className="whitespace-nowrap">{row.phone || "-"}</td>
                <td className="whitespace-nowrap">
                  {row.latitude.toFixed(6)},<br />
                  {row.longitude.toFixed(6)}
                </td>
                <td>
                  <DropdownMenu>
                    <DropdownMenuTrigger asChild>
                      <Button
                        variant="ghost"
                        size="icon-sm"
                        aria-label={`Actions for ${row.name}`}
                      >
                        <MoreHorizontal />
                      </Button>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent align="end">
                      <DropdownMenuItem asChild>
                        <Link href={`/locations/${row.id}`}>
                          <MapPin />
                          View Details
                        </Link>
                      </DropdownMenuItem>
                      {canManage && (
                        <>
                          <DropdownMenuItem
                            onSelect={() => {
                              setEditing(row);
                              setEditor(true);
                            }}
                          >
                            <Pencil />
                            Edit
                          </DropdownMenuItem>
                          <DropdownMenuItem onSelect={() => setDeleting(row)}>
                            <Trash />
                            Delete
                          </DropdownMenuItem>
                        </>
                      )}
                    </DropdownMenuContent>
                  </DropdownMenu>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
        {!rows.length && !visibleError && <EmptyState title="No locations found" />}
      </div>
      {paginationEnabled && (
        <PaginationControls
          pagination={{
            ...pagination,
            total: pagination.total + rows.length - data.length,
            end: pagination.end + rows.length - data.length,
          }}
        />
      )}
      {canManage && <LocationEditor
        open={editor}
        onOpenChange={setEditor}
        location={editing}
        onSave={async (payload) => {
          setError("");
          if (source === "api") {
            const row = await saveLocation(editing?.id, payload);
            setRows((current) =>
              editing
                ? current.map((item) => (item.id === row.id ? row : item))
                : [row, ...current],
            );
            router.refresh();
            setNotice("Location saved.");
            return;
          }
          const row = previewLocation(payload, editing);
          try {
            saveDraft(row);
          } catch {
            throw new Error("Unable to save this preview in browser storage.");
          }
          setRows((current) =>
            editing
              ? current.map((item) => (item.id === row.id ? row : item))
              : [row, ...current],
          );
          setNotice("Location saved in this preview.");
        }}
      />}
      {canManage && <Dialog
        open={!!deleting}
        onOpenChange={(open) => {
          if (!open) setDeleting(undefined);
        }}
      >
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>Delete Location</DialogTitle>
            <DialogDescription>
              {source === "api"
                ? `Delete ${deleting?.name} from the location service?`
                : `Delete ${deleting?.name} from this local preview?`}
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDeleting(undefined)}>
              Cancel
            </Button>
            <Button
              variant="destructive"
              disabled={isDeleting}
              onClick={async () => {
                if (!deleting) return;
                setError("");
                setIsDeleting(true);
                try {
                  if (source === "api") await removeLocation(deleting.id);
                  setRows((current) =>
                    current.filter((row) => row.id !== deleting.id),
                  );
                  if (source === "api") router.refresh();
                  setDeleting(undefined);
                  setNotice(
                    source === "api"
                      ? "Location deleted."
                      : "Location removed from this preview.",
                  );
                } catch (cause) {
                  setError(
                    cause instanceof Error
                      ? cause.message
                      : "Unable to delete this location. Please try again.",
                  );
                } finally {
                  setIsDeleting(false);
                }
              }}
            >
              {isDeleting ? "Deleting..." : "Delete"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>}
    </section>
  );
}

function previewLocation(
  payload: Partial<LocationWritePayload>,
  previous?: Location,
): Location {
  if (
    !payload.code?.trim() ||
    !payload.name?.trim() ||
    !payload.address?.trim() ||
    !payload.currency?.trim() ||
    typeof payload.latitude !== "number" ||
    !Number.isFinite(payload.latitude) ||
    typeof payload.longitude !== "number" ||
    !Number.isFinite(payload.longitude)
  ) {
    throw new Error("Check the required location details and try again.");
  }
  const id = previous?.id ?? `location-demo-${crypto.randomUUID()}`;
  const row: Location = {
    id,
    code: payload.code.trim(),
    name: payload.name.trim(),
    address: payload.address.trim(),
    city: payload.city ?? previous?.city,
    state: previous?.state ?? "",
    country: previous?.country ?? "",
    postalCode: previous?.postalCode ?? "",
    email: payload.email ?? previous?.email ?? "",
    phone: payload.phone ?? previous?.phone ?? "",
    avatarUrl: payload.avatar_url ?? previous?.avatarUrl ?? "",
    latitude: payload.latitude,
    longitude: payload.longitude,
    currency: payload.currency.trim(),
    public: payload.public ?? previous?.public ?? false,
    active: payload.active ?? previous?.active ?? true,
  };
  return row;
}
