import type { Freight } from "@edr/types";
import {
  Box,
  Button,
  Divider,
  Group,
  NumberInput,
  Skeleton,
  Stack,
  Switch,
  Text,
} from "@mantine/core";
import {
  Flame,
  MapPin,
  Plus,
  Route as RouteIcon,
  Snowflake,
  Trash2,
} from "lucide-react";
import { useMemo } from "react";
import {
  Controller,
  useFieldArray,
  type UseFormReturn,
} from "react-hook-form";
import {
  BookingFormInputValues,
  type BookingFormValues,
  getRouteDirection,
} from "./schema";
import { SelectField, StepCard, StepHeader, StepLabel } from "./shared";

type BookingForm = UseFormReturn<
  BookingFormInputValues,
  any,
  BookingFormValues
>;

export function Step4Route({
  form,
  referenceData,
  isLoading,
}: {
  form: BookingForm;
  referenceData?: Freight.BookingReferenceData;
  isLoading?: boolean;
}) {
  const originYard = form.watch("originYard");
  const destinationYard = form.watch("destinationYard");
  const isGeneralContract = form.watch("bookingType") === "general_contract";

  const {
    fields: extraRoutes,
    append: appendRoute,
    remove: removeRoute,
  } = useFieldArray({ control: form.control, name: "extraRoutes" });

  const yardOptions = useMemo(() => {
    if (!referenceData?.yard) return [];
    return referenceData.yard.map((y) => ({ value: y.id, label: y.name }));
  }, [referenceData]);

  const originData = useMemo(() => {
    return yardOptions
      .filter((o) => o.value !== destinationYard)
      .filter((o) => {
        const dest = referenceData?.yard.find((y) => y.id === destinationYard);
        if (!dest) return true;
        const origin = referenceData?.yard.find((y) => y.id === o.value);

        // can't go from Djibouti to Djibouti
        if (dest?.country === "Djibouti" && origin?.country == "Djibouti")
          return false;

        return true;
      });
  }, [yardOptions, destinationYard]);
  const destData = useMemo(() => {
    return yardOptions.filter((o) => o.value !== originYard);
  }, [yardOptions, originYard]);

  const origin = referenceData?.yard.find((y) => y.id === originYard);
  const dest = referenceData?.yard.find((y) => y.id === destinationYard);
  const direction = getRouteDirection(origin, dest);

  const directionStyle: Record<string, string> = {
    EXPORT: "bg-sky-50 text-sky-800 border-sky-200",
    IMPORT: "bg-amber-50 text-amber-800 border-amber-200",
    DOMESTIC: "bg-gray-100 text-gray-600 border-gray-200",
  };
  const directionLabel: Record<string, string> = {
    EXPORT: "Export workflow (inside country to outside country)",
    IMPORT: "Import workflow (outside country to inside country)",
    DOMESTIC: "Domestic corridor",
  };

  const stationSelectDisabled = yardOptions.length === 0;

  // General contracts reserve quantity per route. The unit (items vs tons) comes
  // from the commodity picked in the cargo step, mirroring step5-cargo-details:
  // PER_ITEM → a whole item count; otherwise an estimated tonnage. Container
  // contracts reserve quantity by container count instead, so no quantity input
  // is shown for them here.
  const cargoType = form.watch("cargoType");
  const cargoTypePath = form.watch("cargoTypePath") ?? [];
  const isContainer = cargoType === "container";
  const selectedCommodity = useMemo(() => {
    const parentId = cargoTypePath[0];
    const childId = cargoTypePath[1];
    if (!referenceData?.cargo_type || !parentId || !childId) return null;
    const group = referenceData.cargo_type.find((g) => g.id === parentId);
    return group?.children?.find((c) => c.id === childId) ?? null;
  }, [referenceData, cargoTypePath]);
  const isPerItem = selectedCommodity?.unit_of_measure === "PER_ITEM";
  const quantityLabel = isPerItem ? "Quantity (Items)" : "Quantity (Tons)";
  const quantityStep = isPerItem ? 1 : 0.01;
  const showRouteQuantity = isGeneralContract && !isContainer;

  return (
    <StepCard>
      <StepHeader
        icon={<RouteIcon size={22} />}
        title="Route"
        description="Choose the origin and destination yards for your shipment."
      />

      {isLoading ? (
        <LoadingSkeleton />
      ) : (
        <div className="space-y-3">
          <StepLabel>Route</StepLabel>
          <div className="grid gap-4 sm:grid-cols-2">
            <Controller
              name="originYard"
              control={form.control}
              render={({ field, fieldState }) => (
                <SelectField
                  field={field}
                  error={fieldState.error}
                  label="Origin Yard *"
                  placeholder="Select origin..."
                  disabled={stationSelectDisabled}
                  data={originData}
                />
              )}
            />
            <Controller
              name="destinationYard"
              control={form.control}
              render={({ field, fieldState }) => (
                <SelectField
                  field={field}
                  error={fieldState.error}
                  label="Destination Yard *"
                  placeholder="Select destination..."
                  disabled={stationSelectDisabled}
                  data={destData}
                />
              )}
            />
          </div>
          {direction && (
            <div
              className={`flex items-center gap-2 rounded-lg border px-3 py-2 text-xs font-medium ${directionStyle[direction]}`}
            >
              <MapPin className="h-3.5 w-3.5 shrink-0" />
              {directionLabel[direction]}
            </div>
          )}
          {showRouteQuantity && (
            <Box style={{ maxWidth: 220 }}>
              <Controller
                name="primaryRouteQuantity"
                control={form.control}
                render={({ field, fieldState }) => (
                  <NumberInput
                    label={`${quantityLabel} *`}
                    placeholder={isPerItem ? "e.g. 500" : "e.g. 1200"}
                    description="Quantity reserved on the primary route."
                    min={0}
                    step={quantityStep}
                    error={fieldState.error?.message}
                    value={field.value === "" ? "" : Number(field.value)}
                    onChange={(v) => field.onChange(String(v ?? ""))}
                    radius="md"
                  />
                )}
              />
            </Box>
          )}
        </div>
      )}

      {isGeneralContract && !isLoading && (
        <Box mt={18}>
          <Group justify="space-between" align="center" mb={8}>
            <StepLabel>Additional contract routes</StepLabel>
            <Button
              variant="light"
              color="edr-green"
              size="xs"
              radius="md"
              leftSection={<Plus size={14} />}
              disabled={stationSelectDisabled}
              onClick={() =>
                appendRoute({
                  originYard: "",
                  destinationYard: "",
                  quantity: "",
                  km: "",
                })
              }
            >
              Add route
            </Button>
          </Group>
          <Text fz={12} c="#6B7C8E" mb={12}>
            A general contract can reserve quantity across several routes. The
            route above is your primary route; add more routes and set the
            quantity reserved for each.
          </Text>
          <Stack gap={12}>
            {extraRoutes.map((rf, i) => (
              <Group
                key={rf.id}
                gap={10}
                align="flex-start"
                wrap="nowrap"
                className="rounded-xl"
                style={{ border: "1px solid #E6ECF2", padding: 12 }}
              >
                <Box style={{ flex: 1 }}>
                  <Controller
                    name={`extraRoutes.${i}.originYard`}
                    control={form.control}
                    render={({ field, fieldState }) => (
                      <SelectField
                        field={field}
                        error={fieldState.error}
                        label="Origin"
                        placeholder="Origin..."
                        data={yardOptions}
                      />
                    )}
                  />
                </Box>
                <Box style={{ flex: 1 }}>
                  <Controller
                    name={`extraRoutes.${i}.destinationYard`}
                    control={form.control}
                    render={({ field, fieldState }) => (
                      <SelectField
                        field={field}
                        error={fieldState.error}
                        label="Destination"
                        placeholder="Destination..."
                        data={yardOptions}
                      />
                    )}
                  />
                </Box>
                <Box style={{ width: 140 }}>
                  <Controller
                    name={`extraRoutes.${i}.quantity`}
                    control={form.control}
                    render={({ field }) => (
                      <NumberInput
                        label={quantityLabel}
                        placeholder="0"
                        min={0}
                        step={quantityStep}
                        value={field.value === "" ? "" : Number(field.value)}
                        onChange={(v) => field.onChange(String(v ?? ""))}
                        radius="md"
                      />
                    )}
                  />
                </Box>
                <Box style={{ width: 110 }}>
                  <Controller
                    name={`extraRoutes.${i}.km`}
                    control={form.control}
                    render={({ field }) => (
                      <NumberInput
                        label="Distance (km)"
                        placeholder="0"
                        min={0}
                        step={1}
                        value={field.value === "" ? "" : Number(field.value)}
                        onChange={(v) => field.onChange(String(v ?? ""))}
                        radius="md"
                      />
                    )}
                  />
                </Box>
                <Button
                  variant="subtle"
                  color="red"
                  size="xs"
                  mt={24}
                  px={6}
                  onClick={() => removeRoute(i)}
                >
                  <Trash2 size={16} />
                </Button>
              </Group>
            ))}
          </Stack>
        </Box>
      )}

      <Divider my={22} color="#EEF2F6" />

      <StepLabel>Cargo handling</StepLabel>
      <Stack gap={12} mt={12}>
        <Controller
          name="isHazardous"
          control={form.control}
          render={({ field }) => (
            <ToggleRow
              icon={<Flame size={18} />}
              iconBg="#FBEAE7"
              iconColor="#C0392B"
              title="Hazardous Material"
              description="Applies a hazard surcharge to the final bill."
              checked={field.value}
              onChange={(v) => field.onChange(v)}
            />
          )}
        />
        <Controller
          name="isRefrigerated"
          control={form.control}
          render={({ field }) => (
            <ToggleRow
              icon={<Snowflake size={18} />}
              iconBg="#E9F0F8"
              iconColor="#2E5B96"
              title="Refrigerated Cargo"
              description="Temperature-controlled transport applies a refrigeration surcharge."
              checked={field.value}
              onChange={(v) => field.onChange(v)}
            />
          )}
        />
      </Stack>
    </StepCard>
  );
}

function ToggleRow({
  icon,
  iconBg,
  iconColor,
  title,
  description,
  checked,
  onChange,
}: {
  icon: React.ReactNode;
  iconBg: string;
  iconColor: string;
  title: string;
  description: string;
  checked: boolean;
  onChange: (v: boolean) => void;
}) {
  return (
    <Group
      justify="space-between"
      align="center"
      wrap="nowrap"
      px={16}
      py={13}
      style={{
        borderRadius: 14,
        border: `1.5px solid ${checked ? "#CDEBDD" : "#E6ECF2"}`,
        background: checked ? "#F6FBF8" : "#fff",
        transition: "all 150ms ease",
      }}
    >
      <Group gap={13} align="center" wrap="nowrap">
        <Box
          style={{
            width: 38,
            height: 38,
            borderRadius: 11,
            flexShrink: 0,
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            background: iconBg,
            color: iconColor,
          }}
        >
          {icon}
        </Box>
        <Box>
          <Text fz={14} fw={700} c="#10202F">
            {title}
          </Text>
          <Text fz={12} c="#6B7C8E" style={{ lineHeight: 1.4 }}>
            {description}
          </Text>
        </Box>
      </Group>
      <Switch
        checked={checked}
        onChange={(e) => onChange(e.currentTarget.checked)}
        color="edr-green"
        size="md"
      />
    </Group>
  );
}

function LoadingSkeleton() {
  return (
    <div className="space-y-4 rounded-xl border border-gray-200 p-4">
      <div className="grid gap-3 sm:grid-cols-2">
        <Stack gap={8}>
          <Skeleton height={12} w={80} radius="sm" />
          <Skeleton height={40} radius="md" />
        </Stack>
        <Stack gap={8}>
          <Skeleton height={12} w={96} radius="sm" />
          <Skeleton height={40} radius="md" />
        </Stack>
      </div>
      <Skeleton height={32} radius="md" />
    </div>
  );
}
