import { useMemo, useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import type { ColumnDef } from '@tanstack/react-table';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { parseAsString } from 'nuqs';
import { toast } from 'sonner';
import { Edit, HandHelping, MoreHorizontal, Package, Plus, Trash2 } from 'lucide-react';
import {
  Button,
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@vector/ui';
import { PageHeader } from '../components/layout/PageHeader.js';
import { DataTable } from '../components/data-table/DataTable.js';
import { PartStateBadge, partStateOptions } from '../components/parts/PartStateBadge.js';
import { PartFormDialog } from '../components/parts/PartFormDialog.js';
import { PartBulkStateDialog } from '../components/parts/PartBulkStateDialog.js';
import { ConfirmDialog } from '../components/ConfirmDialog.js';
import { listParts, deletePart } from '../lib/api/parts.js';
import { listManufacturers } from '../lib/api/manufacturers.js';
import { listCategories } from '../lib/api/categories.js';
import { listTags } from '../lib/api/tags.js';
import { takeForRepair } from '../lib/api/custody.js';
import { ApiRequestError } from '../lib/api/client.js';
import type { Part } from '../lib/api/types.js';
import { queryKeys } from '../lib/queryKeys.js';
import { useAuth } from '../contexts/AuthContext.js';

type PartsFilters = {
  state: string | null;
  manufacturerId: string | null;
  categoryId: string | null;
  tagId: string | null;
};

const filterParsers = {
  state: parseAsString,
  manufacturerId: parseAsString,
  categoryId: parseAsString,
  tagId: parseAsString,
};

const ALL = '__all__';

export default function Parts() {
  const { user } = useAuth();
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const isAdmin = user?.role === 'ADMIN';

  const [createOpen, setCreateOpen] = useState(false);
  const [editing, setEditing] = useState<Part | null>(null);
  const [deleting, setDeleting] = useState<Part | null>(null);
  const [bulkIds, setBulkIds] = useState<string[] | null>(null);
  const [clearSelection, setClearSelection] = useState<(() => void) | null>(null);

  const manufacturers = useQuery({
    queryKey: queryKeys.manufacturers.list({ pageSize: 100 }),
    queryFn: () => listManufacturers({ pageSize: 100 }),
  });
  const categoriesQuery = useQuery({
    queryKey: queryKeys.categories.list({ pageSize: 100 }),
    queryFn: () => listCategories({ pageSize: 100 }),
  });
  const tagsQuery = useQuery({
    queryKey: queryKeys.tags.list({ pageSize: 100 }),
    queryFn: () => listTags({ pageSize: 100 }),
  });

  const deleteMutation = useMutation({
    mutationFn: (id: string) => deletePart(id),
    onSuccess: () => {
      toast.success('Part deleted');
      queryClient.invalidateQueries({ queryKey: queryKeys.parts.all });
      setDeleting(null);
    },
    onError: (err) => {
      toast.error(err instanceof ApiRequestError ? err.body.message : 'Delete failed');
    },
  });

  const takeForRepairMutation = useMutation({
    mutationFn: (id: string) => takeForRepair(id),
    onSuccess: () => {
      toast.success('Part moved into your custody');
      queryClient.invalidateQueries({ queryKey: queryKeys.parts.all });
      queryClient.invalidateQueries({ queryKey: queryKeys.custody.all });
    },
    onError: (err) =>
      toast.error(err instanceof ApiRequestError ? err.body.message : 'Could not take part'),
  });

  const columns = useMemo<ColumnDef<Part>[]>(
    () => [
      {
        accessorKey: 'serialNumber',
        header: 'Serial',
        cell: ({ row }) => (
          <Link
            to={`/parts/${row.original.id}`}
            className="font-mono text-xs font-medium text-foreground hover:underline"
          >
            {row.original.serialNumber}
          </Link>
        ),
      },
      {
        id: 'mpn',
        header: 'MPN',
        cell: ({ row }) => (
          <span className="text-sm font-mono">{row.original.partModel.mpn}</span>
        ),
      },
      {
        id: 'manufacturer',
        header: 'Manufacturer',
        cell: ({ row }) => (
          <span className="text-sm text-muted-foreground">{row.original.manufacturer.name}</span>
        ),
      },
      {
        id: 'category',
        header: 'Category',
        cell: ({ row }) =>
          row.original.partModel.category ? (
            <span className="text-xs text-muted-foreground">
              {row.original.partModel.category.name}
            </span>
          ) : (
            <span className="text-xs text-muted-foreground">—</span>
          ),
      },
      {
        accessorKey: 'state',
        header: 'State',
        cell: ({ row }) => <PartStateBadge state={row.original.state} />,
      },
      {
        id: 'location',
        header: 'Location',
        cell: ({ row }) => {
          const { host, custodian, bin } = row.original;
          if (host) {
            return (
              <span className="text-xs font-mono text-muted-foreground">
                {host.assetId} / {host.name}
              </span>
            );
          }
          if (custodian) {
            return (
              <span className="text-xs text-muted-foreground">
                Custody: {custodian.username}
              </span>
            );
          }
          return bin?.fullPath ? (
            <span className="text-xs font-mono text-muted-foreground">{bin.fullPath}</span>
          ) : (
            <span className="text-xs text-muted-foreground italic">Unassigned</span>
          );
        },
      },
      {
        accessorKey: 'price',
        header: 'Price',
        cell: ({ row }) =>
          row.original.price != null ? (
            <span className="text-sm tabular-nums">${row.original.price.toFixed(2)}</span>
          ) : (
            <span className="text-xs text-muted-foreground">—</span>
          ),
      },
      {
        id: 'actions',
        header: () => <span className="sr-only">Actions</span>,
        size: 40,
        cell: ({ row }) => (
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button variant="ghost" size="icon" className="h-7 w-7">
                <MoreHorizontal className="h-4 w-4" />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end" className="w-44">
              <DropdownMenuItem onSelect={() => navigate(`/parts/${row.original.id}`)}>
                View
              </DropdownMenuItem>
              <DropdownMenuItem onSelect={() => setEditing(row.original)}>
                <Edit className="h-3.5 w-3.5" />
                Edit
              </DropdownMenuItem>
              {row.original.state === 'SPARE' && (
                <DropdownMenuItem
                  onSelect={() => takeForRepairMutation.mutate(row.original.id)}
                  disabled={takeForRepairMutation.isPending}
                >
                  <HandHelping className="h-3.5 w-3.5" />
                  Take into custody
                </DropdownMenuItem>
              )}
              {isAdmin && (
                <>
                  <DropdownMenuSeparator />
                  <DropdownMenuItem
                    onSelect={() => setDeleting(row.original)}
                    className="text-destructive focus:text-destructive"
                  >
                    <Trash2 className="h-3.5 w-3.5" />
                    Delete
                  </DropdownMenuItem>
                </>
              )}
            </DropdownMenuContent>
          </DropdownMenu>
        ),
      },
    ],
    [navigate, isAdmin, takeForRepairMutation],
  );

  return (
    <div className="space-y-5">
      <PageHeader
        title="Parts"
        description="Search, filter, and manage every tracked part."
        actions={
          isAdmin && (
            <Button onClick={() => setCreateOpen(true)}>
              <Plus className="h-4 w-4" />
              New part
            </Button>
          )
        }
      />

      <DataTable<Part, PartsFilters>
        columns={columns}
        getRowId={(p) => p.id}
        queryKey={(params) =>
          queryKeys.parts.list({
            page: params.page,
            pageSize: params.pageSize,
            q: params.q,
            sort: params.sort,
            state: params.filters.state,
            manufacturerId: params.filters.manufacturerId,
            categoryId: params.filters.categoryId,
            tagId: params.filters.tagId,
          })
        }
        queryFn={(params) =>
          listParts({
            page: params.page,
            pageSize: params.pageSize,
            q: params.q,
            sort: params.sort,
            state: params.filters.state ?? undefined,
            manufacturerId: params.filters.manufacturerId ?? undefined,
            categoryId: params.filters.categoryId ?? undefined,
            tagId: params.filters.tagId ?? undefined,
          })
        }
        filterParsers={filterParsers}
        searchPlaceholder="Search serial, MPN, notes…"
        enableSelection={isAdmin}
        emptyState={
          <div className="flex flex-col items-center gap-1 py-8 text-muted-foreground">
            <Package className="h-6 w-6" />
            <span className="text-sm">No parts match these filters.</span>
          </div>
        }
        toolbar={({ filters, setFilter }) => (
          <PartsFilters
            manufacturers={manufacturers.data?.data ?? []}
            categories={categoriesQuery.data?.data ?? []}
            tags={tagsQuery.data?.data ?? []}
            state={filters.state ?? ALL}
            manufacturerId={filters.manufacturerId ?? ALL}
            categoryId={filters.categoryId ?? ALL}
            tagId={filters.tagId ?? ALL}
            onState={(v) => setFilter('state', v === ALL ? null : v)}
            onManufacturer={(v) => setFilter('manufacturerId', v === ALL ? null : v)}
            onCategory={(v) => setFilter('categoryId', v === ALL ? null : v)}
            onTag={(v) => setFilter('tagId', v === ALL ? null : v)}
          />
        )}
        bulkActions={(ids, clear) => (
          <Button
            variant="outline"
            size="sm"
            onClick={() => {
              setBulkIds(ids);
              setClearSelection(() => clear);
            }}
          >
            Bulk edit
          </Button>
        )}
      />

      <PartFormDialog open={createOpen} onOpenChange={setCreateOpen} />
      <PartFormDialog
        open={Boolean(editing)}
        onOpenChange={(o) => !o && setEditing(null)}
        part={editing}
      />
      <PartBulkStateDialog
        open={Boolean(bulkIds)}
        onOpenChange={(o) => {
          if (!o) setBulkIds(null);
        }}
        partIds={bulkIds ?? []}
        onDone={() => clearSelection?.()}
      />
      <ConfirmDialog
        open={Boolean(deleting)}
        onOpenChange={(o) => !o && setDeleting(null)}
        title="Delete part?"
        description={
          deleting
            ? `Permanently remove part ${deleting.serialNumber}. Its history will be removed too.`
            : undefined
        }
        confirmLabel="Delete"
        destructive
        pending={deleteMutation.isPending}
        onConfirm={() => deleting && deleteMutation.mutate(deleting.id)}
      />
    </div>
  );
}

interface PartsFiltersProps {
  manufacturers: { id: string; name: string }[];
  categories: { id: string; name: string }[];
  tags: { id: string; name: string }[];
  state: string;
  manufacturerId: string;
  categoryId: string;
  tagId: string;
  onState: (v: string) => void;
  onManufacturer: (v: string) => void;
  onCategory: (v: string) => void;
  onTag: (v: string) => void;
}

function PartsFilters({
  manufacturers,
  categories,
  tags,
  state,
  manufacturerId,
  categoryId,
  tagId,
  onState,
  onManufacturer,
  onCategory,
  onTag,
}: PartsFiltersProps) {
  return (
    <div className="flex items-center gap-2">
      <Select value={state} onValueChange={onState}>
        <SelectTrigger className="h-8 w-36 text-xs">
          <SelectValue placeholder="State" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value={ALL}>All states</SelectItem>
          {partStateOptions.map((o) => (
            <SelectItem key={o.value} value={o.value}>
              {o.label}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
      <Select value={manufacturerId} onValueChange={onManufacturer}>
        <SelectTrigger className="h-8 w-48 text-xs">
          <SelectValue placeholder="Manufacturer" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value={ALL}>All manufacturers</SelectItem>
          {manufacturers.map((m) => (
            <SelectItem key={m.id} value={m.id}>
              {m.name}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
      <Select value={categoryId} onValueChange={onCategory}>
        <SelectTrigger className="h-8 w-40 text-xs">
          <SelectValue placeholder="Category" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value={ALL}>All categories</SelectItem>
          {categories.map((c) => (
            <SelectItem key={c.id} value={c.id}>
              {c.name}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
      <Select value={tagId} onValueChange={onTag}>
        <SelectTrigger className="h-8 w-36 text-xs">
          <SelectValue placeholder="Tag" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value={ALL}>All tags</SelectItem>
          {tags.map((t) => (
            <SelectItem key={t.id} value={t.id}>
              {t.name}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
    </div>
  );
}
