import { useMutation, useQuery } from '@tanstack/react-query';
import { Edit, Eye, Plus, Search, Trash2 } from 'lucide-react';
import { FormEvent, ReactNode, useMemo, useState } from 'react';

import { api } from '@/services/api';
import {
    ActionIcon,
    Box,
    Group,
    Badge as MantineBadge,
    Button as MantineButton,
    Select as MantineSelect,
    Table as MantineTable,
    Modal,
    NumberInput,
    Pagination,
    Paper,
    ScrollArea,
    SimpleGrid,
    Stack,
    Text,
    TextInput,
    Title,
} from '@mantine/core';

import { DeliverCargoDialog } from '@/components/cargoes/DeliverCargoDialog';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { useToast } from '@/hooks/use-toast';
import type { Cargo } from '@/services/cargoService';
import type { Container } from '@/services/containerService';
import type { Locomotive } from '@/services/locomotives.service';
import type { Train } from '@/services/trains.service';
import type { WagonType } from '@/services/wagon-types.service';
import type { Wagon } from '@/services/wagon.service';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@edr/ui-common';

type FormValue = string | number | boolean | string[];

type Field = {
  key: string;
  label: string;
  type?: 'text' | 'number' | 'select';
  required?: boolean;
  options?: { value: string; label: string }[];
  placeholder?: string;
  onValueChange?: (
    value: string,
    current: Record<string, FormValue>,
  ) => Partial<Record<string, FormValue>>;
};

type Column<T> = {
  key: keyof T | string;
  label: string;
  render?: (item: T) => ReactNode;
};

type FleetCrudPageProps<T extends { id: string }> = {
  title: string;
  description: string;
  addLabel: string;
  entityLabel?: string;
  data?: T[];
  isLoading: boolean;
  columns: Column<T>[];
  fields: Field[];
  emptyValues: Record<string, FormValue>;
  searchText: (item: T) => string;
  create: { mutateAsync: (data: Record<string, unknown>) => Promise<unknown>; isPending: boolean };
  update: { mutateAsync: (data: { id: string; data: Record<string, unknown> }) => Promise<unknown>; isPending: boolean };
  remove: { mutateAsync: (id: string) => Promise<unknown>; isPending: boolean };
  removeActionLabel?: string;
  removeConfirmMessage?: string;
  removeSuccessMessage?: string;
  hideViewAction?: boolean;
  /** Optional custom actions rendered before the view/edit/delete buttons in each row. */
  rowActions?: (item: T) => React.ReactNode;
};

const normalizePayload = (values: Record<string, FormValue>) =>
  Object.fromEntries(
    Object.entries(values)
      .map(([key, value]) => [
        key,
        key === 'supportedLoadTypes' && typeof value === 'string'
          ? value
              .split(',')
              .map((entry) => entry.trim())
              .filter(Boolean)
          : Array.isArray(value)
            ? value
            : typeof value === 'string'
              ? value.trim()
              : value,
      ])
      .filter(([, value]) => value !== '' && !(Array.isArray(value) && value.length === 0)),
  );

const extractBackendErrors = (error: unknown) => {
  const responseData = (error as { response?: { data?: unknown } })?.response?.data;
  const data = responseData && typeof responseData === 'object' ? responseData as Record<string, unknown> : undefined;
  const rawMessage = data?.message ?? data?.error ?? (error as Error)?.message;
  const rawErrors = data?.errors;

  const fieldErrors: Record<string, string> = {};
  if (rawErrors && typeof rawErrors === 'object' && !Array.isArray(rawErrors)) {
    Object.entries(rawErrors as Record<string, unknown>).forEach(([field, value]) => {
      fieldErrors[field] = Array.isArray(value) ? value.join(', ') : String(value);
    });
  }

  const message = Array.isArray(rawMessage)
    ? rawMessage.join(', ')
    : rawMessage
      ? String(rawMessage)
      : 'Save failed';

  return { message, fieldErrors };
};

const validateForm = (fields: Field[], values: Record<string, FormValue>) => {
  const errors: Record<string, string> = {};

  fields.forEach((field) => {
    const value = values[field.key];
    const stringValue = typeof value === 'string' ? value.trim() : String(value ?? '');

    if (field.required && stringValue === '') {
      errors[field.key] = `${field.label} is required`;
      return;
    }

    if (field.type === 'number' && stringValue !== '' && !Number.isFinite(Number(value))) {
      errors[field.key] = `${field.label} must be a valid number`;
    }
  });

  return errors;
};

function FleetCrudPage<T extends { id: string }>({
  title,
  description,
  addLabel,
  entityLabel,
  data,
  isLoading,
  columns,
  fields,
  emptyValues,
  searchText,
  create,
  update,
  remove,
  removeActionLabel = 'Delete',
  removeConfirmMessage,
  removeSuccessMessage,
  hideViewAction = false,
  rowActions,
}: FleetCrudPageProps<T>) {
  const [search, setSearch] = useState('');
  const [page, setPage] = useState(1);
  const [sortKey, setSortKey] = useState<string>('');
  const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc');
  const [formOpen, setFormOpen] = useState(false);
  const [editing, setEditing] = useState<T | null>(null);
  const [viewing, setViewing] = useState<T | null>(null);
  const [form, setForm] = useState(emptyValues);
  const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({});
  const { toast } = useToast();

  const filtered = useMemo(() => {
    const query = search.trim().toLowerCase();
    if (!query) return data ?? [];
    return (data ?? []).filter((item) => searchText(item).toLowerCase().includes(query));
  }, [data, search, searchText]);
  const sorted = useMemo(() => {
    if (!sortKey) return filtered;
    return [...filtered].sort((a, b) => {
      const left = (a as Record<string, unknown>)[sortKey];
      const right = (b as Record<string, unknown>)[sortKey];
      const result = String(left ?? '').localeCompare(String(right ?? ''), undefined, { numeric: true });
      return sortDirection === 'asc' ? result : -result;
    });
  }, [filtered, sortDirection, sortKey]);
  const pageSize = 10;
  const pageCount = Math.max(1, Math.ceil(sorted.length / pageSize));
  const paged = sorted.slice((page - 1) * pageSize, page * pageSize);

  const toggleSort = (key: string) => {
    setPage(1);
    if (sortKey === key) {
      setSortDirection((current) => (current === 'asc' ? 'desc' : 'asc'));
      return;
    }
    setSortKey(key);
    setSortDirection('asc');
  };

  const openCreate = () => {
    setEditing(null);
    setForm(emptyValues);
    setFieldErrors({});
    setFormOpen(true);
  };

  const openEdit = (item: T) => {
    setEditing(item);
    setForm(
      Object.fromEntries(
        Object.keys(emptyValues).map((key) => [
          key,
          (item as Record<string, FormValue | null | undefined>)[key] ?? '',
        ]),
      ),
    );
    setFieldErrors({});
    setFormOpen(true);
  };

  const closeForm = () => {
    setFormOpen(false);
    setEditing(null);
    setForm(emptyValues);
    setFieldErrors({});
  };

  const handleSubmit = async (event: FormEvent) => {
    event.preventDefault();
    const validationErrors = validateForm(fields, form);
    if (Object.keys(validationErrors).length > 0) {
      setFieldErrors(validationErrors);
      toast({
        title: 'Save failed',
        description: Object.values(validationErrors)[0],
        variant: 'destructive',
      });
      return;
    }

    const payload = normalizePayload(form);
    setFieldErrors({});

    try {
      if (editing) {
        await update.mutateAsync({ id: editing.id, data: payload });
        toast({ title: `${title.slice(0, -1)} updated` });
      } else {
        await create.mutateAsync(payload);
        toast({ title: `${title.slice(0, -1)} created` });
      }
      closeForm();
    } catch (error) {
      const { message, fieldErrors: backendFieldErrors } = extractBackendErrors(error);
      setFieldErrors(backendFieldErrors);
      toast({ title: 'Save failed', description: message, variant: 'destructive' });
    }
  };

  const handleDelete = async (item: T) => {
    const normalizedEntityLabel = entityLabel ?? title.slice(0, -1);
    if (!window.confirm(removeConfirmMessage ?? `${removeActionLabel} this ${normalizedEntityLabel.toLowerCase()}?`)) return;
    try {
      await remove.mutateAsync(item.id);
      toast({ title: removeSuccessMessage ?? `${normalizedEntityLabel} ${removeActionLabel.toLowerCase()}ed` });
    } catch {
      toast({ title: `${removeActionLabel} failed`, description: 'This record may still be referenced.', variant: 'destructive' });
    }
  };

  const isSaving = create.isPending || update.isPending;

  return (
    <div className="space-y-5 p-6">
      <div className="flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between">
        <div>
          <h1 className="text-2xl font-semibold tracking-tight">{title}</h1>
          <p className="mt-1 text-sm text-muted-foreground">{description}</p>
        </div>
        <Button onClick={openCreate}>
          <Plus className="size-4" />
          {addLabel}
        </Button>
      </div>

      <div className="flex max-w-md items-center gap-2 rounded-md border bg-background px-3">
        <Search className="size-4 text-muted-foreground" />
        <Input
          className="border-0 px-0 shadow-none focus-visible:ring-0"
          placeholder={`Search ${title.toLowerCase()}`}
          value={search}
          onChange={(event) => {
            setSearch(event.target.value);
            setPage(1);
          }}
        />
      </div>

      <div className="overflow-hidden rounded-lg border bg-card">
        <Table>
          <TableHeader>
            <TableRow>
              {columns.map((column) => (
                <TableHead key={String(column.key)}>
                  <button
                    type="button"
                    className="inline-flex items-center gap-1 font-medium"
                    onClick={() => toggleSort(String(column.key))}
                  >
                    {column.label}
                    {sortKey === column.key ? (sortDirection === 'asc' ? 'ASC' : 'DESC') : null}
                  </button>
                </TableHead>
              ))}
              <TableHead className="w-[150px] text-right">Actions</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {paged.map((item) => (
              <TableRow key={item.id}>
                {columns.map((column) => (
                  <TableCell key={String(column.key)}>
                    {column.render ? column.render(item) : String((item as Record<string, unknown>)[String(column.key)] ?? '-')}
                  </TableCell>
                ))}
                <TableCell>
                  <div className="flex justify-end gap-1">
                    {rowActions?.(item)}
                    {!hideViewAction ? (
                      <Button variant="ghost" size="icon" onClick={() => setViewing(item)} title="View">
                        <Eye className="size-4" />
                      </Button>
                    ) : null}
                    <Button variant="ghost" size="icon" onClick={() => openEdit(item)} title="Edit">
                      <Edit className="size-4" />
                    </Button>
                    <Button variant="ghost" size="icon" onClick={() => handleDelete(item)} title={removeActionLabel}>
                      <Trash2 className="size-4" />
                    </Button>
                  </div>
                </TableCell>
              </TableRow>
            ))}
            {!isLoading && filtered.length === 0 ? (
              <TableRow>
                <TableCell colSpan={columns.length + 1} className="h-28 text-center text-muted-foreground">
                  No records found.
                </TableCell>
              </TableRow>
            ) : null}
            {isLoading ? (
              <TableRow>
                <TableCell colSpan={columns.length + 1} className="h-28 text-center text-muted-foreground">
                  Loading...
                </TableCell>
              </TableRow>
            ) : null}
          </TableBody>
        </Table>
      </div>

      <div className="flex items-center justify-between text-sm text-muted-foreground">
        <span>
          Showing {sorted.length === 0 ? 0 : (page - 1) * pageSize + 1}-{Math.min(page * pageSize, sorted.length)} of {sorted.length}
        </span>
        <div className="flex gap-2">
          <Button variant="outline" size="sm" disabled={page === 1} onClick={() => setPage((current) => current - 1)}>
            Previous
          </Button>
          <Button variant="outline" size="sm" disabled={page === pageCount} onClick={() => setPage((current) => current + 1)}>
            Next
          </Button>
        </div>
      </div>

      <Dialog open={formOpen} onOpenChange={(open) => (!open ? closeForm() : setFormOpen(true))}>
        <DialogContent className="max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>{editing ? `Edit ${title.slice(0, -1)}` : addLabel}</DialogTitle>
          </DialogHeader>
          <form className="space-y-4" onSubmit={handleSubmit}>
            {fields.map((field) => {
              const value = form[field.key] ?? '';
              const inputValue = field.type === 'number' && value !== '' && !Number.isFinite(Number(value))
                ? ''
                : Array.isArray(value)
                  ? value.join(', ')
                  : typeof value === 'boolean'
                    ? String(value)
                    : value;
              return (
                <div key={field.key} className="space-y-2">
                  <Label htmlFor={field.key}>{field.label}</Label>
                  {field.type === 'select' ? (
                    <Select
                      value={String(value)}
                      onValueChange={(selectedValue) =>
                        setForm((current) => ({
                          ...current,
                          [field.key]: selectedValue,
                          ...(field.onValueChange?.(selectedValue, current) ?? {}),
                        }) as Record<string, FormValue>)
                      }
                    >
                      <SelectTrigger id={field.key}>
                        <SelectValue placeholder={field.placeholder ?? `Select ${field.label.toLowerCase()}`} />
                      </SelectTrigger>
                      <SelectContent>
                        {field.options?.map((option) => (
                          <SelectItem key={option.value} value={option.value}>
                            {option.label}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                  ) : (
                    <Input
                      id={field.key}
                      type={field.type ?? 'text'}
                      value={inputValue}
                      onChange={(event) =>
                        setForm((current) => ({
                          ...current,
                          [field.key]: field.type === 'number' && event.target.value !== ''
                            ? Number(event.target.value)
                            : event.target.value,
                        }))
                      }
                    />
                  )}
                  {fieldErrors[field.key] ? (
                    <p className="text-sm text-destructive">{fieldErrors[field.key]}</p>
                  ) : null}
                </div>
              );
            })}
            <DialogFooter>
              <Button type="button" variant="outline" onClick={closeForm}>
                Cancel
              </Button>
              <Button type="submit" disabled={isSaving}>
                Save
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <Dialog open={Boolean(viewing)} onOpenChange={(open) => (!open ? setViewing(null) : null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>{title.slice(0, -1)} details</DialogTitle>
          </DialogHeader>
          <div className="grid gap-3 text-sm">
            {viewing
              ? Object.entries(viewing).map(([key, value]) => (
                  <div key={key} className="grid grid-cols-[150px,1fr] gap-3 border-b pb-2">
                    <span className="font-medium">{key}</span>
                    <span className="break-all text-muted-foreground">{value == null ? '-' : String(value)}</span>
                  </div>
                ))
              : null}
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}

const statusBadge = (status?: string) => <Badge variant="outline">{status ?? '-'}</Badge>;

const optionLabel = (options: { value: string; label: string }[], value?: string | null) =>
  options.find((option) => option.value === value)?.label ?? value ?? '-';

export function TrainMasterDataPage() {
  const query = useQuery(api.trains.list.queryOptions());
  return (
    <FleetCrudPage<Train>
      title="Trains"
      description="Manage train master data independently from train scheduling."
      addLabel="Add Train"
      data={query.data}
      isLoading={query.isLoading}
      create={useMutation(api.trains.create.mutationOptions())}
      update={useMutation(api.trains.update.mutationOptions())}
      remove={useMutation(api.trains.remove.mutationOptions())}
      searchText={(train) => [train.code, train.trainNumber, train.trainName, train.status].join(' ')}
      columns={[
        { key: 'code', label: 'Code' },
        { key: 'trainNumber', label: 'Number', render: (train) => train.trainNumber || '-' },
        { key: 'trainName', label: 'Name', render: (train) => train.trainName || '-' },
        { key: 'capacityTons', label: 'Capacity (tons)' },
        { key: 'status', label: 'Status', render: (train) => statusBadge(train.status) },
      ]}
      fields={[
        { key: 'code', label: 'Code', required: true },
        { key: 'capacityTons', label: 'Capacity (tons)', type: 'number', required: true },
        { key: 'trainNumber', label: 'Train number' },
        { key: 'trainName', label: 'Train name' },
        { key: 'locomotiveNumber', label: 'Locomotive number' },
        { key: 'status', label: 'Status' },
        { key: 'notes', label: 'Notes' },
        { key: 'remarks', label: 'Remarks' },
      ]}
      emptyValues={{ code: '', capacityTons: 0, trainNumber: '', trainName: '', locomotiveNumber: '', status: 'AVAILABLE', notes: '', remarks: '' }}
    />
  );
}

export function WagonTypesCrudPage() {
  const query = useQuery(api.wagonTypes.list.queryOptions());
  const create = useMutation(api.wagonTypes.create.mutationOptions());
  const update = useMutation(api.wagonTypes.update.mutationOptions());
  const remove = useMutation(api.wagonTypes.remove.mutationOptions());
  const { toast } = useToast();
  const [search, setSearch] = useState('');
  const [page, setPage] = useState(1);
  const [sortKey, setSortKey] = useState<keyof WagonType>('code');
  const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc');
  const [formOpen, setFormOpen] = useState(false);
  const [editing, setEditing] = useState<WagonType | null>(null);
  const [viewing, setViewing] = useState<WagonType | null>(null);
  const [form, setForm] = useState<Record<string, FormValue>>({
    code: '',
    name: '',
    capacityTons: 0,
    lengthMeters: 0,
    maxWagonsPerTrain: '',
    supportedLoadTypes: '',
    isActive: true,
  });
  const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({});

  const pageSize = 10;
  const filtered = useMemo(() => {
    const queryText = search.trim().toLowerCase();
    const rows = query.data ?? [];
    if (!queryText) return rows;
    return rows.filter((type) =>
      [type.code, type.name, type.supportedLoadTypes?.join(' '), type.isActive ? 'active' : 'inactive']
        .join(' ')
        .toLowerCase()
        .includes(queryText),
    );
  }, [query.data, search]);

  const sorted = useMemo(() => {
    return [...filtered].sort((left, right) => {
      const result = String(left[sortKey] ?? '').localeCompare(String(right[sortKey] ?? ''), undefined, {
        numeric: true,
      });
      return sortDirection === 'asc' ? result : -result;
    });
  }, [filtered, sortDirection, sortKey]);

  const pageCount = Math.max(1, Math.ceil(sorted.length / pageSize));
  const paged = sorted.slice((page - 1) * pageSize, page * pageSize);
  const isSaving = create.isPending || update.isPending;

  const toggleSort = (key: keyof WagonType) => {
    setPage(1);
    if (sortKey === key) {
      setSortDirection((current) => (current === 'asc' ? 'desc' : 'asc'));
      return;
    }
    setSortKey(key);
    setSortDirection('asc');
  };

  const closeForm = () => {
    setFormOpen(false);
    setEditing(null);
    setFieldErrors({});
    setForm({
      code: '',
      name: '',
      capacityTons: 0,
      lengthMeters: 0,
      maxWagonsPerTrain: '',
      supportedLoadTypes: '',
      isActive: true,
    });
  };

  const openEdit = (type: WagonType) => {
    setEditing(type);
    setFieldErrors({});
    setForm({
      code: type.code ?? '',
      name: type.name ?? '',
      capacityTons: type.capacityTons ?? 0,
      lengthMeters: type.lengthMeters ?? 0,
      maxWagonsPerTrain: type.maxWagonsPerTrain ?? '',
      supportedLoadTypes: type.supportedLoadTypes?.join(', ') ?? '',
      isActive: type.isActive,
    });
    setFormOpen(true);
  };

  const validateWagonType = () => {
    const errors: Record<string, string> = {};
    if (!String(form.code ?? '').trim()) errors.code = 'Code is required';
    if (!String(form.name ?? '').trim()) errors.name = 'Name is required';
    if (!Number.isFinite(Number(form.capacityTons))) errors.capacityTons = 'Capacity must be a valid number';
    if (!Number.isFinite(Number(form.lengthMeters))) errors.lengthMeters = 'Length must be a valid number';
    return errors;
  };

  const handleSubmit = async (event: FormEvent) => {
    event.preventDefault();
    const errors = validateWagonType();
    if (Object.keys(errors).length > 0) {
      setFieldErrors(errors);
      toast({ title: 'Save failed', description: Object.values(errors)[0], variant: 'destructive' });
      return;
    }

    const payload = normalizePayload(form);
    setFieldErrors({});

    try {
      if (editing) {
        await update.mutateAsync({ id: editing.id, data: payload });
        toast({ title: 'Wagon Type updated' });
      } else {
        await create.mutateAsync(payload);
        toast({ title: 'Wagon Type created' });
      }
      closeForm();
    } catch (error) {
      const { message, fieldErrors: backendFieldErrors } = extractBackendErrors(error);
      setFieldErrors(backendFieldErrors);
      toast({ title: 'Save failed', description: message, variant: 'destructive' });
    }
  };

  const handleDelete = async (type: WagonType) => {
    if (!window.confirm('Delete this wagon type?')) return;
    try {
      await remove.mutateAsync(type.id);
      toast({ title: 'Wagon Type deleted' });
    } catch {
      toast({ title: 'Delete failed', description: 'This wagon type may still be referenced.', variant: 'destructive' });
    }
  };

  const sortLabel = (key: keyof WagonType) => (sortKey === key ? (sortDirection === 'asc' ? ' ASC' : ' DESC') : '');

  return (
    <Box p="lg">
      <Stack gap="md">
        <Group justify="space-between" align="flex-end">
          <Box>
            <Title order={2}>Wagon Types</Title>
            <Text size="sm" c="dimmed" mt={4}>
              Manage wagon type capacities and load compatibility used by wagon master data.
            </Text>
          </Box>
          <MantineButton
            leftSection={<Plus size={16} />}
            onClick={() => {
              closeForm();
              setFormOpen(true);
            }}
          >
            Add Wagon Type
          </MantineButton>
        </Group>

        <TextInput
          maw={420}
          leftSection={<Search size={16} />}
          placeholder="Search wagon types"
          value={search}
          onChange={(event) => {
            setSearch(event.currentTarget.value);
            setPage(1);
          }}
        />

        <Paper withBorder radius="md">
          <ScrollArea>
            <MantineTable striped highlightOnHover verticalSpacing="sm" miw={900}>
              <MantineTable.Thead>
                <MantineTable.Tr>
                  <MantineTable.Th>
                    <MantineButton variant="subtle" size="compact-sm" onClick={() => toggleSort('code')}>
                      Code{sortLabel('code')}
                    </MantineButton>
                  </MantineTable.Th>
                  <MantineTable.Th>
                    <MantineButton variant="subtle" size="compact-sm" onClick={() => toggleSort('name')}>
                      Name{sortLabel('name')}
                    </MantineButton>
                  </MantineTable.Th>
                  <MantineTable.Th>
                    <MantineButton variant="subtle" size="compact-sm" onClick={() => toggleSort('capacityTons')}>
                      Capacity (tons){sortLabel('capacityTons')}
                    </MantineButton>
                  </MantineTable.Th>
                  <MantineTable.Th>Length (m)</MantineTable.Th>
                  <MantineTable.Th>Load types</MantineTable.Th>
                  <MantineTable.Th>Status</MantineTable.Th>
                  <MantineTable.Th ta="right">Actions</MantineTable.Th>
                </MantineTable.Tr>
              </MantineTable.Thead>
              <MantineTable.Tbody>
                {paged.map((type) => (
                  <MantineTable.Tr key={type.id}>
                    <MantineTable.Td fw={600}>{type.code}</MantineTable.Td>
                    <MantineTable.Td>{type.name}</MantineTable.Td>
                    <MantineTable.Td>{type.capacityTons}</MantineTable.Td>
                    <MantineTable.Td>{type.lengthMeters}</MantineTable.Td>
                    <MantineTable.Td>{type.supportedLoadTypes?.join(', ') || '-'}</MantineTable.Td>
                    <MantineTable.Td>
                      <MantineBadge color={type.isActive === false ? 'gray' : 'edr-green'} variant="light">
                        {type.isActive === false ? 'Inactive' : 'Active'}
                      </MantineBadge>
                    </MantineTable.Td>
                    <MantineTable.Td>
                      <Group gap="xs" justify="flex-end">
                        <ActionIcon variant="subtle" aria-label="View wagon type" onClick={() => setViewing(type)}>
                          <Eye size={16} />
                        </ActionIcon>
                        <ActionIcon variant="subtle" aria-label="Edit wagon type" onClick={() => openEdit(type)}>
                          <Edit size={16} />
                        </ActionIcon>
                        <ActionIcon
                          color="red"
                          variant="subtle"
                          aria-label="Delete wagon type"
                          onClick={() => handleDelete(type)}
                        >
                          <Trash2 size={16} />
                        </ActionIcon>
                      </Group>
                    </MantineTable.Td>
                  </MantineTable.Tr>
                ))}
                {!query.isLoading && filtered.length === 0 ? (
                  <MantineTable.Tr>
                    <MantineTable.Td colSpan={7}>
                      <Text ta="center" c="dimmed" py="xl">
                        No wagon types found.
                      </Text>
                    </MantineTable.Td>
                  </MantineTable.Tr>
                ) : null}
                {query.isLoading ? (
                  <MantineTable.Tr>
                    <MantineTable.Td colSpan={7}>
                      <Text ta="center" c="dimmed" py="xl">
                        Loading...
                      </Text>
                    </MantineTable.Td>
                  </MantineTable.Tr>
                ) : null}
              </MantineTable.Tbody>
            </MantineTable>
          </ScrollArea>
        </Paper>

        <Group justify="space-between">
          <Text size="sm" c="dimmed">
            Showing {sorted.length === 0 ? 0 : (page - 1) * pageSize + 1}-{Math.min(page * pageSize, sorted.length)} of{' '}
            {sorted.length}
          </Text>
          <Pagination total={pageCount} value={page} onChange={setPage} size="sm" />
        </Group>
      </Stack>

      <Modal opened={formOpen} onClose={closeForm} title={editing ? 'Edit Wagon Type' : 'Add Wagon Type'} centered>
        <form onSubmit={handleSubmit}>
          <Stack>
            <SimpleGrid cols={{ base: 1, sm: 2 }}>
              <TextInput
                label="Code"
                required
                value={String(form.code ?? '')}
                error={fieldErrors.code}
                onChange={(event) => setForm((current) => ({ ...current, code: event.currentTarget.value }))}
              />
              <TextInput
                label="Name"
                required
                value={String(form.name ?? '')}
                error={fieldErrors.name}
                onChange={(event) => setForm((current) => ({ ...current, name: event.currentTarget.value }))}
              />
              <NumberInput
                label="Capacity (tons)"
                required
                min={0}
                value={Number(form.capacityTons ?? 0)}
                error={fieldErrors.capacityTons}
                onChange={(value) => setForm((current) => ({ ...current, capacityTons: value }))}
              />
              <NumberInput
                label="Length (meters)"
                required
                min={0}
                value={Number(form.lengthMeters ?? 0)}
                error={fieldErrors.lengthMeters}
                onChange={(value) => setForm((current) => ({ ...current, lengthMeters: value }))}
              />
              <NumberInput
                label="Max wagons per train"
                min={0}
                value={form.maxWagonsPerTrain === '' ? '' : Number(form.maxWagonsPerTrain)}
                onChange={(value) => setForm((current) => ({ ...current, maxWagonsPerTrain: value }))}
              />
              <MantineSelect
                label="Status"
                value={form.isActive ? 'true' : 'false'}
                data={[
                  { value: 'true', label: 'Active' },
                  { value: 'false', label: 'Inactive' },
                ]}
                onChange={(value) => setForm((current) => ({ ...current, isActive: value !== 'false' }))}
              />
            </SimpleGrid>
            <TextInput
              label="Supported load types"
              placeholder="container, break-bulk"
              value={Array.isArray(form.supportedLoadTypes) ? form.supportedLoadTypes.join(', ') : String(form.supportedLoadTypes ?? '')}
              onChange={(event) => setForm((current) => ({ ...current, supportedLoadTypes: event.currentTarget.value }))}
            />
            <Group justify="flex-end">
              <MantineButton variant="default" type="button" onClick={closeForm}>
                Cancel
              </MantineButton>
              <MantineButton type="submit" loading={isSaving}>
                Save
              </MantineButton>
            </Group>
          </Stack>
        </form>
      </Modal>

      <Modal opened={Boolean(viewing)} onClose={() => setViewing(null)} title="Wagon Type details" centered>
        <Stack gap="xs">
          {viewing
            ? Object.entries(viewing).map(([key, value]) => (
                <Group key={key} justify="space-between" align="flex-start" wrap="nowrap">
                  <Text size="sm" fw={600}>
                    {key}
                  </Text>
                  <Text size="sm" c="dimmed" ta="right">
                    {Array.isArray(value) ? value.join(', ') : value == null ? '-' : String(value)}
                  </Text>
                </Group>
              ))
            : null}
        </Stack>
      </Modal>
    </Box>
  );
}

export function WagonsCrudPage() {
  const query = useQuery(api.wagons.list.queryOptions({ input: {} }));
  const { data: wagonTypes = [] } = useQuery(api.wagonTypes.list.queryOptions());
  const { data: yards = [] } = useQuery(api.routes.yards.queryOptions());
  const wagonTypeOptions = wagonTypes.map((type: any) => ({
    value: type.id,
    label: `${type.code} - ${type.name}`,
  }));
  const yardOptions = yards.map((yard: any) => ({
    value: yard.id,
    label: `${yard.label ?? yard.code} (${yard.country ?? '-'})`,
  }));
  return (
    <FleetCrudPage<Wagon>
      title="Wagons"
      description="Manage wagon master data. Booking-based train assignment is handled in train scheduling."
      addLabel="Add Wagon"
      data={query.data}
      isLoading={query.isLoading}
      create={useMutation(api.wagons.create.mutationOptions())}
      update={useMutation(api.wagons.update.mutationOptions())}
      remove={useMutation(api.wagons.remove.mutationOptions())}
      searchText={(wagon) => [
        wagon.wagonNumber,
        wagon.wagonTypeId,
        wagon.trainId,
        wagon.status,
        wagon.currentLocationYard?.label,
        wagon.currentLocationYard?.code,
        wagon.currentLocationYard?.country,
      ].join(' ')}
      columns={[
        { key: 'wagonNumber', label: 'Number' },
        { key: 'wagonTypeId', label: 'Type', render: (wagon) => optionLabel(wagonTypeOptions, wagon.wagonTypeId) },
        {
          key: 'currentLocationYardId',
          label: 'Location',
          render: (wagon) =>
            wagon.currentLocationYard
              ? `${wagon.currentLocationYard.label ?? wagon.currentLocationYard.code} (${wagon.currentLocationYard.country ?? '-'})`
              : '-',
        },
        { key: 'maxPayloadWeight', label: 'Max payload' },
        { key: 'status', label: 'Status', render: (wagon) => statusBadge(wagon.status) },
      ]}
      fields={[
        { key: 'wagonNumber', label: 'Wagon number', required: true },
        {
          key: 'wagonTypeId',
          label: 'Wagon type',
          type: 'select',
          required: true,
          options: wagonTypeOptions,
          onValueChange: (value, current) => {
            const selectedType = wagonTypes.find((type: any) => type.id === value);
            if (!selectedType || Number(current.maxPayloadWeight) > 0) return {};
            return { maxPayloadWeight: Number(selectedType.capacityTons) };
          },
        },
        {
          key: 'currentLocationYardId',
          label: 'Wagon location',
          type: 'select',
          required: true,
          options: yardOptions,
        },
        { key: 'tareWeight', label: 'Tare weight', type: 'number', required: true },
        { key: 'maxPayloadWeight', label: 'Max payload weight', type: 'number', required: true },
        {
          key: 'status',
          label: 'Status',
          type: 'select',
          options: [
            { value: 'AVAILABLE', label: 'Available' },
            { value: 'IMPORT_READY', label: 'Import ready' },
            { value: 'EXPORT_READY', label: 'Export ready' },
            { value: 'ASSIGNED', label: 'Assigned' },
            { value: 'MAINTENANCE', label: 'Maintenance' },
            { value: 'RETIRED', label: 'Retired' },
          ],
        },
        { key: 'notes', label: 'Notes' },
      ]}
      emptyValues={{ wagonNumber: '', wagonTypeId: '', currentLocationYardId: '', tareWeight: 0, maxPayloadWeight: 0, status: 'AVAILABLE', notes: '' }}
    />
  );
}

export function ContainersCrudPage() {
  const query = useQuery(api.containers.list.queryOptions());
  const { data: containerTypes = [] } = useQuery(
    api.containerTypes.list.queryOptions({ staleTime: Infinity }),
  );
  const { data: wagons = [] } = useQuery(api.wagons.list.queryOptions({ input: {} }));
  const containerTypeOptions = containerTypes.map((type: any) => ({
    value: type.id,
    label: type.label ?? type.name ?? type.code,
  }));
  const wagonOptions = wagons.map((wagon: Wagon) => ({
    value: wagon.id,
    label: wagon.wagonNumber,
  }));
  return (
    <FleetCrudPage<Container>
      title="Containers"
      description="Manage container master data and wagon assignments."
      addLabel="Add Container"
      data={query.data}
      isLoading={query.isLoading}
      create={useMutation(api.containers.create.mutationOptions())}
      update={useMutation(api.containers.update.mutationOptions())}
      remove={useMutation(api.containers.remove.mutationOptions())}
      searchText={(container) => [container.containerNumber, container.containerTypeId, container.wagonId, container.status].join(' ')}
      columns={[
        { key: 'containerNumber', label: 'Number' },
        { key: 'containerTypeId', label: 'Type', render: (container) => optionLabel(containerTypeOptions, container.containerTypeId) },
        { key: 'wagonId', label: 'Wagon', render: (container) => optionLabel(wagonOptions, container.wagonId) },
        { key: 'maxGrossWeight', label: 'Max gross' },
        { key: 'status', label: 'Status', render: (container) => statusBadge(container.status) },
      ]}
      fields={[
        { key: 'containerNumber', label: 'Container number', required: true },
        {
          key: 'containerTypeId',
          label: 'Container type',
          type: 'select',
          required: true,
          options: containerTypeOptions,
        },
        {
          key: 'wagonId',
          label: 'Wagon',
          type: 'select',
          options: [{ value: 'none', label: 'Unassigned' }, ...wagonOptions],
          onValueChange: (value) => (value === 'none' ? { wagonId: '' } : {}),
        },
        { key: 'position', label: 'Position', type: 'number' },
        { key: 'tareWeight', label: 'Tare weight', type: 'number', required: true },
        { key: 'maxGrossWeight', label: 'Max gross weight', type: 'number', required: true },
        { key: 'sealNumber', label: 'Seal number' },
        { key: 'status', label: 'Status' },
      ]}
      emptyValues={{ containerNumber: '', containerTypeId: '', wagonId: '', position: '', tareWeight: 0, maxGrossWeight: 0, sealNumber: '', status: 'AVAILABLE' }}
    />
  );
}

export function CargoesCrudPage() {
  const query = useQuery(api.cargoes.list.queryOptions());
  const { data: cargoTypes = [] } = useQuery(
    api.cargoTypes.list.queryOptions({ staleTime: Infinity }),
  );
  const { data: containers = [] } = useQuery(api.containers.list.queryOptions());
  const cargoTypeOptions = cargoTypes.map((type: any) => ({
    value: type.id,
    label: type.cargoTypeName ?? type.cargo_type_name ?? type.name ?? type.code,
  }));
  const containerOptions = containers.map((container: Container) => ({
    value: container.id,
    label: container.containerNumber,
  }));
  return (
    <FleetCrudPage<Cargo>
      title="Cargoes"
      description="Manage cargo records linked to containers."
      addLabel="Add Cargo"
      data={query.data}
      isLoading={query.isLoading}
      create={useMutation(api.cargoes.create.mutationOptions())}
      update={useMutation(api.cargoes.update.mutationOptions())}
      remove={useMutation(api.cargoes.remove.mutationOptions())}
      searchText={(cargo) => [cargo.cargoReference, cargo.description, cargo.containerId, cargo.status].join(' ')}
      columns={[
        { key: 'cargoReference', label: 'Reference' },
        { key: 'cargoTypeId', label: 'Cargo type', render: (cargo) => optionLabel(cargoTypeOptions, cargo.cargoTypeId) },
        { key: 'containerId', label: 'Container', render: (cargo) => optionLabel(containerOptions, cargo.containerId) },
        { key: 'quantity', label: 'Quantity' },
        { key: 'weight', label: 'Weight' },
        { key: 'status', label: 'Status', render: (cargo) => statusBadge(cargo.status) },
        {
          key: 'receiverName',
          label: 'Proof of delivery',
          render: (cargo) =>
            cargo.status === 'DELIVERED' && cargo.receiverName
              ? `${cargo.receiverName}${cargo.deliveredAt ? ` · ${new Date(cargo.deliveredAt).toLocaleDateString()}` : ''}`
              : '—',
        },
      ]}
      rowActions={(cargo) =>
        cargo.status === 'LOADED' ? <DeliverCargoDialog cargoId={cargo.id} /> : null
      }
      fields={[
        { key: 'cargoReference', label: 'Cargo reference', required: true },
        { key: 'shipmentId', label: 'Shipment ID', required: true },
        {
          key: 'containerId',
          label: 'Container',
          type: 'select',
          required: true,
          options: containerOptions,
        },
        {
          key: 'cargoTypeId',
          label: 'Cargo type',
          type: 'select',
          options: cargoTypeOptions,
        },
        { key: 'description', label: 'Description' },
        { key: 'quantity', label: 'Quantity', type: 'number', required: true },
        { key: 'weight', label: 'Weight', type: 'number', required: true },
        { key: 'volume', label: 'Volume', type: 'number' },
        { key: 'status', label: 'Status' },
      ]}
      emptyValues={{ cargoReference: '', shipmentId: '', containerId: '', cargoTypeId: '', description: '', quantity: 0, weight: 0, volume: '', status: 'PENDING' }}
    />
  );
}

export function LocomotivesCrudPage() {
  const query = useQuery(api.locomotives.list.queryOptions());

  return (
    <FleetCrudPage<Locomotive>
      title="Locomotives"
      entityLabel="Locomotive"
      description="Manage locomotive master data used by train scheduling and fleet operations."
      addLabel="Add Locomotive"
      data={query.data}
      isLoading={query.isLoading}
      create={useMutation(api.locomotives.create.mutationOptions())}
      update={useMutation(api.locomotives.update.mutationOptions())}
      remove={useMutation(api.locomotives.decommission.mutationOptions())}
      removeActionLabel="Decommission"
      removeConfirmMessage="Decommission this locomotive?"
      removeSuccessMessage="Locomotive decommissioned"
      searchText={(locomotive) =>
        [
          locomotive.code,
          locomotive.name,
          locomotive.locomotiveType,
          locomotive.status,
        ].join(' ')
      }
      columns={[
        { key: 'code', label: 'Code' },
        { key: 'name', label: 'Name', render: (locomotive) => locomotive.name || '-' },
        { key: 'locomotiveType', label: 'Type' },
        { key: 'status', label: 'Status', render: (locomotive) => statusBadge(locomotive.status) },
        { key: 'maxPullWeightTons', label: 'Max pull (tons)' },
        { key: 'maxTrainLengthMeters', label: 'Max length (m)' },
      ]}
      fields={[
        { key: 'code', label: 'Code', required: true },
        { key: 'name', label: 'Name' },
        {
          key: 'locomotiveType',
          label: 'Locomotive type',
          type: 'select',
          required: true,
          options: [
            { value: 'DIESEL', label: 'Diesel' },
            { value: 'ELECTRIC', label: 'Electric' },
          ],
        },
        {
          key: 'status',
          label: 'Status',
          type: 'select',
          required: true,
          options: [
            { value: 'AVAILABLE', label: 'Available' },
            { value: 'MAINTENANCE', label: 'Maintenance' },
            { value: 'ASSIGNED', label: 'Assigned' },
            { value: 'OUT_OF_SERVICE', label: 'Out of service' },
          ],
        },
        { key: 'maxPullWeightTons', label: 'Max pulling weight (tons)', type: 'number', required: true },
        { key: 'maxTrainLengthMeters', label: 'Max train length (meters)', type: 'number', required: true },
        { key: 'powerKw', label: 'Power (kW)', type: 'number' },
        { key: 'tractionForceKn', label: 'Traction force (kN)', type: 'number' },
        { key: 'maxSpeedKmh', label: 'Max speed (km/h)', type: 'number' },
      ]}
      emptyValues={{
        code: '',
        name: '',
        locomotiveType: 'DIESEL',
        status: 'AVAILABLE',
        maxPullWeightTons: 0,
        maxTrainLengthMeters: 760,
        powerKw: '',
        tractionForceKn: '',
        maxSpeedKmh: '',
      }}
    />
  );
}
