import { useEffect, useState } from "react";
import { Button, Card, Group, NumberInput, Stack } from "@mantine/core";

import { PageContainer, PageHeader } from "@/components/page";
import DurationField from "@/components/trainScheduling/DurationField";
import { trainSchedulingService } from "@/services/trainScheduling.service";
import { useToast } from "@/hooks/use-toast";
import type { TrainSchedulingGlobalRules } from "@/types/trainScheduling";

export default function TrainSchedulingGlobalRulesPage() {
  const { toast } = useToast();
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  // Fields hold raw NumberInput values (number | string) while editing; coerced to Number on save.
  const [form, setForm] = useState<
    Partial<Record<keyof TrainSchedulingGlobalRules, number | string>>
  >({});

  useEffect(() => {
    void (async () => {
      try {
        const rules = await trainSchedulingService.getGlobalRules();
        // `numeric` columns come back from the API as strings (e.g. "250.00").
        // Coerce every field to a real number so Mantine's controlled
        // NumberInput edits cleanly (a string value fights the caret) and the
        // default can be cleared and replaced.
        const numeric: Partial<Record<keyof TrainSchedulingGlobalRules, number | string>> = {};
        for (const [key, value] of Object.entries(rules)) {
          if (key === "id") continue;
          const num = value === "" || value == null ? "" : Number(value);
          numeric[key as keyof TrainSchedulingGlobalRules] =
            typeof num === "number" && Number.isNaN(num) ? "" : num;
        }
        setForm(numeric);
      } catch {
        toast({ title: "Failed to load train scheduling rules", variant: "destructive" });
      } finally {
        setLoading(false);
      }
    })();
    // Run once on mount only. `toast` from useToast is a fresh function every
    // render — listing it here re-fired the effect on every render, refetching
    // the rules and overwriting whatever the user was typing (values snapped
    // back to the saved defaults).
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const handleSave = async () => {
    // Every field must hold a real number — an empty box (cleared but not
    // refilled) must not silently save as 0. Collect the numeric payload and
    // reject if any value is blank or NaN.
    const fields: (keyof TrainSchedulingGlobalRules)[] = [
      "maxTrainLengthMeters",
      "maxTrainWeightTons",
      "maxWagonsPerTrain",
      "max20ftContainerWeightTons",
      "max20ftPairWeightDiffTons",
      "importWindowLeadDays",
      "exportBookingLeadHours",
      "windowOpenHour",
      "windowDurationHours",
      "docReviewMinutes",
      "paymentWindowMinutes",
      "reopenDelayMinutes",
    ];
    const payload: Partial<Record<keyof TrainSchedulingGlobalRules, number>> = {};
    for (const key of fields) {
      const raw = form[key];
      const num = raw === "" || raw == null ? NaN : Number(raw);
      if (!Number.isFinite(num)) {
        toast({
          title: "All fields are required — fill every value before saving.",
          variant: "destructive",
        });
        return;
      }
      payload[key] = num;
    }

    setSaving(true);
    try {
      const updated = await trainSchedulingService.updateGlobalRules(payload);
      setForm(updated);
      toast({ title: "Train scheduling rules saved" });
    } catch {
      toast({ title: "Failed to save rules", variant: "destructive" });
    } finally {
      setSaving(false);
    }
  };

  return (
    <PageContainer>
      <PageHeader
        title="Train scheduling rules"
        subtitle="Global limits applied when previewing and assigning bookings to trains."
      />

      <Card maw={720}>
        <Stack gap="md">
          <NumberInput
            label="Max train length (m)"
            description="Sum of all wagon lengths must not exceed this"
            value={form.maxTrainLengthMeters ?? ""}
            onChange={(value) =>
              setForm((current) => ({ ...current, maxTrainLengthMeters: value }))
            }
            clampBehavior="none"
            allowDecimal
            min={1}
            disabled={loading}
          />
          <NumberInput
            label="Max train weight (T)"
            description="Total container and bulk cargo weight must not exceed this"
            value={form.maxTrainWeightTons ?? ""}
            onChange={(value) =>
              setForm((current) => ({ ...current, maxTrainWeightTons: value }))
            }
            clampBehavior="none"
            allowDecimal
            min={1}
            disabled={loading}
          />
          <NumberInput
            label="Max wagons per train"
            value={form.maxWagonsPerTrain ?? ""}
            onChange={(value) =>
              setForm((current) => ({ ...current, maxWagonsPerTrain: value }))
            }
            clampBehavior="none"
            allowDecimal
            min={1}
            disabled={loading}
          />
          <NumberInput
            label="Max 20ft container weight (T)"
            description="Each individual 20ft container gross weight limit"
            value={form.max20ftContainerWeightTons ?? ""}
            onChange={(value) =>
              setForm((current) => ({
                ...current,
                max20ftContainerWeightTons: value,
              }))
            }
            clampBehavior="none"
            allowDecimal
            min={0.001}
            disabled={loading}
          />
          <NumberInput
            label="Max 20ft pair weight difference (T)"
            description="When two 20ft containers share a wagon, |weight1 − weight2| must not exceed this"
            value={form.max20ftPairWeightDiffTons ?? ""}
            onChange={(value) =>
              setForm((current) => ({
                ...current,
                max20ftPairWeightDiffTons: value,
              }))
            }
            clampBehavior="none"
            allowDecimal
            min={0}
            disabled={loading}
          />
        </Stack>
      </Card>

      <Card maw={720} mt="md">
        <Stack gap="md">
          <PageHeader
            title="Booking windows"
            subtitle="Import booking-day cycle and export lead time. All times in Addis Ababa (EAT)."
          />
          <DurationField
            label="Import window lead"
            description="The single booking day opens this long before departure"
            value={form.importWindowLeadDays ?? ""}
            nativeUnit="days"
            onChange={(value) =>
              setForm((current) => ({ ...current, importWindowLeadDays: value }))
            }
            min={0}
            disabled={loading}
          />
          <DurationField
            label="Export booking lead"
            description="Export bookings are accepted first-come-first-serve starting this long before departure"
            value={form.exportBookingLeadHours ?? ""}
            nativeUnit="hours"
            onChange={(value) =>
              setForm((current) => ({ ...current, exportBookingLeadHours: value }))
            }
            min={1}
            disabled={loading}
          />
          <NumberInput
            label="Window open hour (EAT)"
            description="Local hour the import window opens on its booking day (e.g. 8 = 08:00)"
            value={form.windowOpenHour ?? ""}
            onChange={(value) =>
              setForm((current) => ({ ...current, windowOpenHour: value }))
            }
            clampBehavior="none"
            allowDecimal
            min={0}
            max={23}
            disabled={loading}
          />
          <DurationField
            label="Window duration"
            description="How long the import booking window stays open"
            value={form.windowDurationHours ?? ""}
            nativeUnit="hours"
            onChange={(value) =>
              setForm((current) => ({ ...current, windowDurationHours: value }))
            }
            min={1}
            disabled={loading}
          />
          <DurationField
            label="Document review"
            description="Max staff time to accept booking documents after the window closes"
            value={form.docReviewMinutes ?? ""}
            nativeUnit="minutes"
            onChange={(value) =>
              setForm((current) => ({ ...current, docReviewMinutes: value }))
            }
            min={0}
            disabled={loading}
          />
          <DurationField
            label="Payment window"
            description="Time a selected customer has to pay before the slot expires"
            value={form.paymentWindowMinutes ?? ""}
            nativeUnit="minutes"
            onChange={(value) =>
              setForm((current) => ({ ...current, paymentWindowMinutes: value }))
            }
            min={1}
            disabled={loading}
          />
          <DurationField
            label="Reopen delay"
            description="Delay after window close before reopening when the train is not full (90 min = 11:00 close → 12:30 reopen)"
            value={form.reopenDelayMinutes ?? ""}
            nativeUnit="minutes"
            onChange={(value) =>
              setForm((current) => ({ ...current, reopenDelayMinutes: value }))
            }
            min={1}
            disabled={loading}
          />
          <Group justify="flex-end">
            <Button loading={saving} disabled={loading} onClick={() => void handleSave()}>
              Save rules
            </Button>
          </Group>
        </Stack>
      </Card>
    </PageContainer>
  );
}
