"use client";

import { useState, useCallback, useMemo } from "react";
import { toast } from "sonner";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { MoreHorizontal, Loader2, Car, Wifi, WifiOff, TrendingUp, Cable, ShieldCheck, Unplug } from "lucide-react";
import { useRepositories } from "@/di/repository-provider";
import { useT, useLocale } from "@/shared/i18n/client";
import { formatDate } from "@/shared/lib/format-date";
import { useApiQuery } from "@/presentation/hooks/use-api-query";
import { usePageHeader } from "@/presentation/hooks/use-page-header";
import { useApiMutation } from "@/presentation/hooks/use-api-mutation";
import { useCrudMutations } from "@/presentation/hooks/use-crud-mutations";
import { useDeleteTarget } from "@/presentation/hooks/use-delete-target";
import { useServerPagination } from "@/presentation/hooks/use-server-pagination";
import ServerDataTable from "@/presentation/components/shared/server-data-table";
import StatsCard from "@/presentation/components/shared/stats-card";
import ConfirmationDialog from "@/presentation/components/shared/confirmation-dialog";
import { StatusBadge, ConnectionStatusBadge } from "@/presentation/components/shared/status-badge";
import { Button } from "@/presentation/components/ui/button";
import { Input } from "@/presentation/components/ui/input";
import {
  Dialog, DialogContent, DialogHeader, DialogTitle,
} from "@/presentation/components/ui/dialog";
import {
  DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger,
} from "@/presentation/components/ui/dropdown-menu";
import { SearchableSelect } from "@/presentation/components/ui/searchable-select";
import CompanyLinkbycarDisconnectDialog from "@/presentation/components/vehicles/company-linkbycar-disconnect-dialog";
import {
  Form, FormControl, FormField, FormItem, FormLabel, FormMessage,
} from "@/presentation/components/ui/form";
import { updateVehicleSchema, type UpdateVehicleFormValues } from "@/shared/schemas/vehicle.schema";
import type { Vehicle } from "@/domain/entities/vehicle";
import type { Column } from "@/presentation/components/shared/server-data-table";

export default function VehiclesPage() {
  const t = useT();
  const locale = useLocale();
  usePageHeader(t.pages.vehicles.title, t.pages.vehicles.subtitle);
  const container = useRepositories();
  const pagination = useServerPagination();
  const [editOpen, setEditOpen] = useState(false);
  const [editingVehicle, setEditingVehicle] = useState<Vehicle | null>(null);
  const deleteDialog = useDeleteTarget<Vehicle>();
  const [disconnectTarget, setDisconnectTarget] = useState<Vehicle | null>(null);
  const [companyDisconnectOpen, setCompanyDisconnectOpen] = useState(false);

  // The company-wide action reuses the list filter rather than adding a second
  // company picker: the operator is already looking at that company's fleet.
  const filteredCompanyId = pagination.filters.company_id
    ? Number(pagination.filters.company_id)
    : null;

  const { data: stats } = useApiQuery(
    () => container.vehicleRepository.getStats(),
    { deps: [] }
  );

  const { data: companyOptions } = useApiQuery(
    () => container.companyRepository.getOptions(),
    { deps: [] }
  );

  const { data: providerOptions } = useApiQuery(
    () => container.vehicleRepository.getProviderOptions(),
    { deps: [] }
  );

  const { data: response, loading, refetch } = useApiQuery(
    () => container.vehicleRepository.findAll(pagination.params),
    { deps: [pagination.params] }
  );

  const { update: updateMutation, delete: deleteMutation } = useCrudMutations(
    container.vehicleRepository,
    {
      update: { successMessage: t.vehicles.toasts.updated, onSuccess: () => { setEditOpen(false); setEditingVehicle(null); refetch(); } },
      delete: { successMessage: t.vehicles.toasts.deleted, onSuccess: () => { deleteDialog.close(); refetch(); } },
    }
  );

  const connectLinkbycarMutation = useApiMutation(
    (id: number) => container.vehicleRepository.connectLinkbycar(id),
    { successMessage: t.vehicles.toasts.linkbycarConnected, onSuccess: refetch }
  );

  // The endpoint returns only a message, not the new status. Refetch on success (badge -> Eligible) and on
  // error too: a 422 downgrades a previously-Eligible badge server-side, so re-pull to keep the row exact.
  const testEligibilityMutation = useApiMutation(
    (id: number) => container.vehicleRepository.testEligibility(id),
    {
      loadingMessage: t.vehicles.toasts.eligibilityChecking,
      successMessage: t.vehicles.toasts.eligibilityChecked,
      onSuccess: refetch,
      onError: () => refetch(),
    }
  );

  // Both outcomes are successes and differ only in wording, so the toast comes
  // from the returned `outcome` — api.post() unwraps to `data` and drops the
  // backend message that would otherwise carry the distinction.
  const disconnectLinkbycarMutation = useApiMutation(
    (id: number) => container.vehicleRepository.disconnectLinkbycar(id),
    {
      loadingMessage: t.vehicles.toasts.linkbycarDisconnecting,
      onSuccess: (result) => {
        toast.success(
          result?.outcome === "not_registered"
            ? t.vehicles.toasts.linkbycarNotRegistered
            : t.vehicles.toasts.linkbycarDisconnected
        );
        setDisconnectTarget(null);
        refetch();
      },
    }
  );

  const schema = useMemo(() => updateVehicleSchema(t), [t]);
  const form = useForm<UpdateVehicleFormValues>({
    resolver: zodResolver(schema),
  });

  const openEdit = useCallback((vehicle: Vehicle) => {
    setEditingVehicle(vehicle);
    form.reset({
      numberplate: vehicle.numberplate,
      mark: vehicle.mark,
      model: vehicle.model,
      motor_type: vehicle.motor_type,
      site_id: vehicle.site?.id ?? null,
      driver_id: null,
    });
    setEditOpen(true);
  }, [form]);

  const columns: Column<Vehicle>[] = [
    { key: "numberplate", label: t.vehicles.columns.numberplate, sortable: true },
    {
      key: "vin",
      label: t.vehicles.columns.vin,
      // The API may omit the VIN or send an empty string — both render as a dash.
      render: (row) => (
        <span className="font-mono text-xs text-muted-foreground">
          {row.vin?.trim() ? row.vin : "—"}
        </span>
      ),
    },
    { key: "mark", label: t.vehicles.columns.mark, sortable: true },
    { key: "model", label: t.vehicles.columns.model },
    { key: "motor_type", label: t.vehicles.columns.motorType },
    {
      key: "connection_status",
      label: t.vehicles.columns.connection,
      render: (row) => <ConnectionStatusBadge label={row.connection_status.label} color={row.connection_status.color} />,
    },
    {
      key: "company",
      label: t.forms.company,
      render: (row) => row.company?.name ?? "—",
    },
    {
      key: "provider",
      label: t.vehicles.columns.provider,
      render: (row) => row.provider ?? "—",
    },
    {
      key: "status",
      label: t.forms.status,
      sortable: true,
      render: (row) => <StatusBadge status={row.status} />,
    },
    {
      key: "created_at",
      label: t.common.createdAt,
      sortable: true,
      render: (row) => formatDate(row.created_at, locale),
    },
    {
      key: "actions",
      label: "",
      className: "w-10",
      render: (row) => (
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant="ghost" size="icon-sm" onClick={(e) => e.stopPropagation()}>
              <MoreHorizontal className="w-4 h-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end" onClick={(e) => e.stopPropagation()}>
            <DropdownMenuItem onClick={() => openEdit(row)}>{t.common.edit}</DropdownMenuItem>
            {/* Offered until the vehicle is connected. color "success" = Connected (locale-independent, unlike the label). */}
            {row.connection_status.color !== "success" && (
              <DropdownMenuItem
                disabled={testEligibilityMutation.loading}
                onClick={() => testEligibilityMutation.mutate(row.id)}
              >
                <ShieldCheck className="w-4 h-4 mr-2" />
                {t.vehicles.actions.testEligibility}
              </DropdownMenuItem>
            )}
            {row.vin && row.connection_status.label === "Eligible" && (
              <DropdownMenuItem
                disabled={connectLinkbycarMutation.loading}
                onClick={() => connectLinkbycarMutation.mutate(row.id)}
              >
                <Cable className="w-4 h-4 mr-2" />
                {t.vehicles.actions.connectLinkbycar}
              </DropdownMenuItem>
            )}
            {/* Offered only where there is something to release: "success" = Connected,
                "warning" = Pending (locale-independent, unlike the labels). Rows whose
                local status lies about being disconnected are caught by the company-wide
                catch-up sweep instead. */}
            {row.vin && ["success", "warning"].includes(row.connection_status.color) && (
              <DropdownMenuItem
                disabled={disconnectLinkbycarMutation.loading}
                onClick={() => setDisconnectTarget(row)}
              >
                <Unplug className="w-4 h-4 mr-2" />
                {t.vehicles.actions.disconnectLinkbycar}
              </DropdownMenuItem>
            )}
            <DropdownMenuSeparator />
            <DropdownMenuItem className="text-destructive" onClick={() => deleteDialog.open(row)}>{t.common.delete}</DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      ),
    },
  ];

  return (
    <div className="p-6 space-y-6">

      {stats && (
        <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
          <StatsCard title={t.vehicles.stats.total} value={stats.total} icon={Car} accent="blue" />
          <StatsCard title={t.vehicles.stats.connected} value={stats.connected} icon={Wifi} accent="green" />
          <StatsCard title={t.vehicles.stats.notConnected} value={stats.not_connected} icon={WifiOff} accent="red" />
          <StatsCard title={t.vehicles.stats.new30d} value={stats.new_last_30_days} icon={TrendingUp} accent="purple" />
        </div>
      )}

      <ServerDataTable
        columns={columns}
        data={response?.items ?? []}
        total={response?.total ?? 0}
        page={pagination.page}
        totalPages={response?.last_page ?? 1}
        loading={loading}
        search={pagination.search}
        onSearchChange={pagination.setSearch}
        onPageChange={pagination.setPage}
        onSortChange={pagination.setSort}
        sortBy={pagination.orderBy}
        sortOrder={pagination.order}
        toolbar={
          <>
            <SearchableSelect
              label={t.vehicles.columns.connection}
              triggerClassName="w-36"
              placeholder={t.vehicles.columns.connection}
              value={(pagination.filters.connection_status as string) ?? "all"}
              onValueChange={(v) => pagination.setFilter("connection_status", v === "all" ? undefined : v)}
              options={[
                { value: "all", label: t.common.all },
                { value: "N", label: t.vehicles.connectionFilter.notConnected },
                { value: "E", label: t.vehicles.connectionFilter.eligible },
                { value: "P", label: t.vehicles.connectionFilter.pending },
                { value: "C", label: t.vehicles.connectionFilter.connected },
              ]}
            />
            <SearchableSelect
              label={t.forms.company}
              triggerClassName="w-44"
              placeholder={t.forms.company}
              value={(pagination.filters.company_id as string) ?? "all"}
              onValueChange={(v) => pagination.setFilter("company_id", v === "all" ? undefined : v)}
              options={[
                { value: "all", label: t.common.allF },
                ...(companyOptions?.map((c) => ({ value: String(c.value), label: c.label })) ?? []),
              ]}
            />
            <SearchableSelect
              label={t.vehicles.columns.provider}
              triggerClassName="w-44"
              placeholder={t.vehicles.columns.provider}
              value={(pagination.filters.provider as string) ?? "all"}
              onValueChange={(v) => pagination.setFilter("provider", v === "all" ? undefined : v)}
              options={[
                { value: "all", label: t.common.all },
                ...(providerOptions?.map((p) => ({ value: p.value, label: p.label })) ?? []),
              ]}
            />
            <SearchableSelect
              label={t.forms.status}
              triggerClassName="w-32"
              placeholder={t.forms.status}
              value={(pagination.filters.status as string) ?? "all"}
              onValueChange={(v) => pagination.setFilter("status", v === "all" ? undefined : v)}
              options={[
                { value: "all", label: t.common.all },
                { value: "0", label: t.users.statusFilter.pending },
                { value: "1", label: t.users.statusFilter.active },
                { value: "2", label: t.users.statusFilter.disabled },
              ]}
            />
            {/* Left enabled with no company selected on purpose: a disabled button
                cannot explain itself, so the dialog says which filter to set. */}
            <Button variant="outline" size="sm" onClick={() => setCompanyDisconnectOpen(true)}>
              <Unplug className="w-4 h-4 mr-2" />
              {t.vehicles.actions.disconnectCompany}
            </Button>
          </>
        }
      />

      <Dialog open={editOpen} onOpenChange={setEditOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader><DialogTitle>{t.vehicles.dialog.titleEdit}</DialogTitle></DialogHeader>
          <Form {...form}>
            <form onSubmit={form.handleSubmit((v) => editingVehicle && updateMutation.mutate({ id: editingVehicle.id, data: v }))} className="space-y-4">
              <FormField control={form.control} name="numberplate" render={({ field }) => (
                <FormItem><FormLabel>{t.vehicles.columns.numberplate}</FormLabel><FormControl><Input {...field} value={field.value ?? ""} /></FormControl><FormMessage /></FormItem>
              )} />
              <div className="grid grid-cols-2 gap-4">
                <FormField control={form.control} name="mark" render={({ field }) => (
                  <FormItem><FormLabel>{t.vehicles.columns.mark}</FormLabel><FormControl><Input {...field} value={field.value ?? ""} /></FormControl><FormMessage /></FormItem>
                )} />
                <FormField control={form.control} name="model" render={({ field }) => (
                  <FormItem><FormLabel>{t.vehicles.columns.model}</FormLabel><FormControl><Input {...field} value={field.value ?? ""} /></FormControl><FormMessage /></FormItem>
                )} />
              </div>
              <FormField control={form.control} name="motor_type" render={({ field }) => (
                <FormItem><FormLabel>{t.vehicles.fields.motorTypeLong}</FormLabel><FormControl><Input {...field} value={field.value ?? ""} /></FormControl><FormMessage /></FormItem>
              )} />
              <div className="flex justify-end gap-2 pt-2">
                <Button type="button" variant="outline" onClick={() => setEditOpen(false)}>{t.common.cancel}</Button>
                <Button type="submit" disabled={updateMutation.loading}>
                  {updateMutation.loading && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
                  {t.common.save}
                </Button>
              </div>
            </form>
          </Form>
        </DialogContent>
      </Dialog>

      <ConfirmationDialog
        open={deleteDialog.isOpen}
        onOpenChange={(open) => !open && deleteDialog.close()}
        title={t.vehicles.delete.title}
        description={t.vehicles.delete.description(deleteDialog.target?.numberplate ?? undefined)}
        confirmLabel={t.common.delete}
        variant="destructive"
        loading={deleteMutation.loading}
        onConfirm={() => deleteDialog.target && deleteMutation.mutate(deleteDialog.target.id)}
      />

      <ConfirmationDialog
        open={disconnectTarget !== null}
        onOpenChange={(open) => !open && setDisconnectTarget(null)}
        title={t.vehicles.disconnect.title}
        description={t.vehicles.disconnect.description(disconnectTarget?.numberplate ?? undefined)}
        confirmLabel={t.vehicles.disconnect.confirm}
        variant="destructive"
        loading={disconnectLinkbycarMutation.loading}
        onConfirm={() => disconnectTarget && disconnectLinkbycarMutation.mutate(disconnectTarget.id)}
      />

      <CompanyLinkbycarDisconnectDialog
        open={companyDisconnectOpen}
        onOpenChange={setCompanyDisconnectOpen}
        companyId={filteredCompanyId}
        onQueued={refetch}
      />
    </div>
  );
}
