import type { ColumnDef } from "@edr/ui-common";
import { DataTable, DataTableFooter, usePagination } from "@edr/ui-common";
import {
  ActionIcon,
  Badge,
  Box,
  Button,
  Card,
  Group,
  Select,
  Stack,
  Text,
  TextInput,
} from "@mantine/core";
import { useDebouncedValue } from "@mantine/hooks";
import { keepPreviousData, useQuery } from "@tanstack/react-query";
import {
  Hammer,
  Pencil,
  Ruler,
  Search,
  Train as TrainIcon,
  TrainFront,
  Weight,
} from "lucide-react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";

import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
import BuildTrainModal from "@/components/trainBuilder/BuildTrainModal";
import EditTrainDetailsModal from "@/components/trainBuilder/EditTrainDetailsModal";
import {
  trainStatusColor,
  trainStatusLabel,
} from "@/components/trainBuilder/trainStatus";
import { api } from "@/services/api";
import { useAuth } from "@/auth/useAuth";
import { canFleetAction } from "@/lib/permissions";
import type {
  BuiltTrainListFilters,
  BuiltTrainStatus,
  BuiltTrainSummary,
} from "@/services/trainBuilder.service";

/**
 * Train Builder board: every built train (code, yard, locomotive set, consist
 * totals, lifecycle status) plus the entry point for building a new one.
 */
export default function TrainBuilderListPage() {
  const navigate = useNavigate();
  const { pagination, setPagination } = usePagination({ pageSize: 10 });
  const [search, setSearch] = useState("");
  const [debouncedSearch] = useDebouncedValue(search, 300);
  const [statusFilter, setStatusFilter] = useState<"ALL" | BuiltTrainStatus>("ALL");
  const [yardFilter, setYardFilter] = useState("ALL");
  const [buildOpen, setBuildOpen] = useState(false);
  const [editTarget, setEditTarget] = useState<BuiltTrainSummary | null>(null);
  const { user } = useAuth();
  const canCreate = canFleetAction(user, "trains", "create");
  const canUpdate = canFleetAction(user, "trains", "update");

  const resetPage = useCallback(() => {
    setPagination((prev) =>
      prev.pageIndex === 0 ? prev : { ...prev, pageIndex: 0 },
    );
  }, [setPagination]);

  useEffect(() => {
    resetPage();
  }, [debouncedSearch, resetPage]);

  const filters = useMemo<BuiltTrainListFilters>(
    () => ({
      page: pagination.pageIndex + 1,
      pageSize: pagination.pageSize,
      ...(debouncedSearch.trim() ? { search: debouncedSearch.trim() } : {}),
      ...(statusFilter !== "ALL" ? { status: statusFilter } : {}),
      ...(yardFilter !== "ALL" ? { currentYardId: yardFilter } : {}),
      sortBy: "createdAt",
      sortOrder: "DESC",
    }),
    [
      pagination.pageIndex,
      pagination.pageSize,
      debouncedSearch,
      statusFilter,
      yardFilter,
    ],
  );

  const trainsQuery = useQuery(
    api.trainBuilder.list.queryOptions({
      input: { filters },
      placeholderData: keepPreviousData,
      staleTime: 30_000,
    }),
  );
  const yardsQuery = useQuery(api.routes.yards.queryOptions({ staleTime: 5 * 60_000 }));

  const trains = trainsQuery.data?.items ?? [];
  const totalTrains = trainsQuery.data?.meta.total ?? 0;
  const pageCount = Math.max(1, trainsQuery.data?.meta.totalPages ?? 1);

  const stats = useMemo(() => {
    const base = { available: 0, scheduled: 0, inService: 0, wagons: 0 };
    for (const train of trains) {
      if (train.status === "AVAILABLE") base.available += 1;
      if (train.status === "SCHEDULED") base.scheduled += 1;
      if (train.status === "IN_SERVICE") base.inService += 1;
      base.wagons += train.wagonCount;
    }
    return base;
  }, [trains]);

  const yardOptions = useMemo(
    () =>
      (yardsQuery.data ?? []).map((y) => ({
        value: y.id,
        label: y.label ?? y.code,
      })),
    [yardsQuery.data],
  );

  const columns = useMemo((): ColumnDef<BuiltTrainSummary>[] => {
    const headerClassName = ruleEngineTable.headerCell;
    const cellClassName = ruleEngineTable.bodyCell;
    return [
      {
        id: "code",
        header: "Train",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => (
          <Group gap="sm" wrap="nowrap">
            <Box
              style={{
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                width: 34,
                height: 34,
                borderRadius: 9,
                background: "var(--mantine-color-edr-green-0)",
                color: "var(--mantine-color-edr-green-7)",
                flexShrink: 0,
              }}
            >
              <TrainIcon size={16} />
            </Box>
            <Stack gap={0}>
              <Text size="sm" fw={600} ff="monospace" lh={1.2}>
                {row.original.code}
              </Text>
              <Text size="xs" c="dimmed" lh={1.2}>
                {row.original.trainName ?? "—"}
              </Text>
            </Stack>
          </Group>
        ),
      },
      {
        id: "numbers",
        header: "Train No.",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => {
          const active = row.original.activeSchedule;
          return (
            <Stack gap={2}>
              {active?.trainNumber ? (
                <Text size="sm" fw={700} ff="monospace" lh={1.2}>
                  {active.trainNumber}
                </Text>
              ) : null}
              <Text size="xs" c="dimmed" ff="monospace" lh={1.2}>
                IMP {row.original.importTrainNumber ?? "—"} · EXP{" "}
                {row.original.exportTrainNumber ?? "—"}
              </Text>
            </Stack>
          );
        },
      },
      {
        id: "yard",
        header: "Yard",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => (
          <Text size="sm">{row.original.currentYard?.label ?? "—"}</Text>
        ),
      },
      {
        id: "locomotives",
        header: "Locomotives",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => {
          const locos = row.original.locomotives;
          if (!locos.length) {
            return (
              <Text size="sm" c="dimmed">
                —
              </Text>
            );
          }
          return (
            <Group gap={6} wrap="nowrap">
              <TrainFront size={14} color="var(--mantine-color-gray-5)" />
              <Text size="sm" fw={500}>
                {locos.map((l) => l.code).join(" + ")}
              </Text>
            </Group>
          );
        },
      },
      {
        id: "consist",
        header: "Consist",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => (
          <Text size="sm">
            {row.original.wagonCount} wagons · {row.original.totalTareTons}T tare ·{" "}
            {row.original.totalLengthMeters}m
          </Text>
        ),
      },
      {
        id: "capacity",
        header: "Haul limit",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => (
          <Text size="sm" fw={500}>
            {row.original.maxPullWeightTons}T
          </Text>
        ),
      },
      {
        id: "status",
        header: "Status",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => (
          <Badge color={trainStatusColor(row.original.status)} variant="light">
            {trainStatusLabel(row.original.status)}
          </Badge>
        ),
      },
      {
        id: "actions",
        header: "",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) =>
          canUpdate ? (
            <ActionIcon
              variant="subtle"
              color="gray"
              aria-label={`Edit train ${row.original.code}`}
              title="Edit name & train numbers"
              onClick={(e) => {
                // Row click navigates to the detail page — keep the edit local.
                e.stopPropagation();
                setEditTarget(row.original);
              }}
            >
              <Pencil size={15} />
            </ActionIcon>
          ) : null,
      },
    ];
  }, [canUpdate]);

  const tableStatus = trainsQuery.isLoading
    ? "loading"
    : trainsQuery.isError
      ? "error"
      : "success";

  return (
    <PageContainer>
      <PageHeader
        title="Train Builder"
        subtitle="Assemble coded trains from locomotives and wagons in a yard, ready to schedule as a unit."
        action={
          canCreate ? (
            <Button leftSection={<Hammer size={18} />} onClick={() => setBuildOpen(true)}>
              Build train
            </Button>
          ) : undefined
        }
      />

      <KpiStrip
        items={[
          { label: "Trains", value: totalTrains, icon: TrainIcon },
          { label: "Available", value: stats.available, icon: Hammer },
          { label: "Scheduled / in service", value: stats.scheduled + stats.inService, icon: Weight },
          { label: "Wagons coupled", value: stats.wagons, icon: Ruler },
        ]}
      />

      <Card p={0}>
        <Stack gap={0}>
          <Box px="md" pt="md" pb="sm" w="100%">
            <Group gap="sm" wrap="wrap">
              <TextInput
                size="sm"
                radius="lg"
                placeholder="Search by code or name…"
                leftSection={<Search size={14} />}
                value={search}
                onChange={(e) => setSearch(e.currentTarget.value)}
                style={{ flex: 1, minWidth: 220 }}
              />
              <Select
                size="sm"
                radius="lg"
                value={statusFilter}
                onChange={(v) => {
                  if (!v) return;
                  setStatusFilter(v as "ALL" | BuiltTrainStatus);
                  resetPage();
                }}
                data={[
                  { value: "ALL", label: "All statuses" },
                  { value: "AVAILABLE", label: "Available" },
                  { value: "SCHEDULED", label: "Scheduled" },
                  { value: "IN_SERVICE", label: "In service" },
                  { value: "UNDER_MAINTENANCE", label: "Under maintenance" },
                  { value: "OUT_OF_SERVICE", label: "Out of service" },
                  { value: "DEACTIVATED", label: "Deactivated" },
                ]}
                w={180}
                styles={{ input: { borderColor: "var(--mantine-color-gray-3)" } }}
              />
              <Select
                size="sm"
                radius="lg"
                placeholder="Yard"
                searchable
                value={yardFilter}
                onChange={(v) => {
                  setYardFilter(v ?? "ALL");
                  resetPage();
                }}
                data={[{ value: "ALL", label: "All yards" }, ...yardOptions]}
                w={170}
                styles={{ input: { borderColor: "var(--mantine-color-gray-3)" } }}
              />
            </Group>
          </Box>

          <DataTable
            columns={columns}
            data={trains}
            status={tableStatus}
            onRowClick={(train) => navigate(`/dashboard/train-builder/${train.id}`)}
            error={
              trainsQuery.isError
                ? {
                    message: "Failed to load trains.",
                    onRetry: () => void trainsQuery.refetch(),
                  }
                : undefined
            }
            emptyMessage="No trains built yet — build the first one"
            pagination={{
              pageIndex: pagination.pageIndex,
              pageSize: pagination.pageSize,
              pageCount,
              totalCount: totalTrains,
            }}
            tableOptions={{
              manualPagination: true,
              pageCount,
              state: { pagination },
              onPaginationChange: setPagination,
            }}
            containerClassName="border-0 shadow-none bg-transparent"
            footer={({ table, pagination: footerPagination }) => (
              <DataTableFooter
                table={table}
                pagination={footerPagination}
                options={{ labels: { items: "trains" } }}
              />
            )}
          />
        </Stack>
      </Card>

      <BuildTrainModal
        opened={buildOpen}
        onClose={() => setBuildOpen(false)}
        onBuilt={(composition) => navigate(`/dashboard/train-builder/${composition.id}`)}
      />

      <EditTrainDetailsModal train={editTarget} onClose={() => setEditTarget(null)} />
    </PageContainer>
  );
}
