"use client";

import React, {
  memo,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import {
  Alert,
  Box,
  Button,
  Chip,
  CircularProgress,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  IconButton,
  Stack,
  TextField,
  Typography,
} from "@mui/material";
import { alpha } from "@mui/material/styles";
import {
  AlertCircle,
  Calendar,
  Clock,
  Columns,
  ListFilter,
  Save,
  Upload,
  X,
} from "lucide-react";
import { useTranslation } from "react-i18next";
import {
  createTruckLaneScheduleClient,
  planTruckLaneScheduleFromRouteExcelClient,
  type RouteExcelSchedulePlanCounts,
  type RouteExcelSchedulePlanError,
  type RouteExcelSchedulePlanPreviewRow,
  type TruckLaneScheduleLineRequest,
} from "@/app/api/shop/client";
import { formatScheduleTargetLaneLabel } from "@/components/Shop/scheduleRouteExcelToMoves";
import ScheduleDragWorkspacePane from "@/components/Shop/ScheduleDragWorkspacePane";
import ScheduleReviewQueue from "@/components/Shop/ScheduleReviewQueue";
import { extractApiErrorMessage } from "@/components/Shop/scheduleClientHelpers";
import {
  defaultFocusedLaneIds,
  initPlannedLanes,
  listModifications,
  moveShop,
  removeShopFromPlan,
  restoreDeletedShop,
  revertShop,
  setShopLoadingSequence,
  toScheduleMappings,
  type ScheduleDragWorkspaceState,
  type ScheduledDeleteSnapshot,
} from "@/components/Shop/scheduleDragWorkspace";
import { buildExecuteAtIso } from "@/components/Shop/scheduleExecuteAt";
import { validateScheduleLines } from "@/components/Shop/scheduleLineValidation";
import {
  formatScheduleValidationErrors,
} from "@/components/Shop/scheduleUiHelpers";
import { validatePlannedSubmit } from "@/components/Shop/truckLaneMovePlanner";
import {
  dedupeDistrictPendingOrder,
  formatPlannedShopLocation,
} from "@/components/Shop/routeBoardDisplayOrder";

export type ScheduleLaneShopSnapshot = {
  truckRowId: number;
  districtReferenceRaw: string | null;
  loadingSequence: number;
};

export type ScheduleLaneOption = {
  id: string;
  label: string;
  truckLanceCode: string;
  remark?: string | null;
  storeId: string;
  shops: ScheduleLaneShopSnapshot[];
};

export type ScheduleShopRow = {
  truckRowId: number;
  shopCode: string;
  /** Resolved title (shop table name or branch fallback). */
  displayName: string;
  /** Truck row branch name for card subtitle. */
  branchName: string;
  storeId: string;
  location: string;
  districtDisplay: string;
  districtReferenceRaw: string | null;
  currentLaneId: string;
  currentLaneLabel: string;
};

export type ScheduleMoveSelection = {
  laneId: string;
  toLoadingSequence: number;
};

export type ScheduleChangePayload = {
  date: string;
  time: string;
  mappings: Record<number, ScheduleMoveSelection>;
  plannedLanes: ScheduleDragWorkspaceState;
  pendingDeletes: ScheduledDeleteSnapshot[];
};

type Props = {
  open: boolean;
  onClose: () => void;
  lanes: ScheduleLaneOption[];
  shops: ScheduleShopRow[];
  pendingTruckRowIds: Set<number>;
  onConfirmManual: (payload: ScheduleChangePayload) => void | Promise<void>;
  onAfterScheduleChange?: () => void | Promise<void>;
};

const ScheduleChangeModal: React.FC<Props> = ({
  open,
  onClose,
  lanes,
  shops,
  pendingTruckRowIds,
  onConfirmManual,
  onAfterScheduleChange,
}) => {
  const { t } = useTranslation("shop");
  const importFileRef = useRef<HTMLInputElement>(null);
  const [tab, setTab] = useState<"manual" | "import">("manual");
  const [scheduledDate, setScheduledDate] = useState("");
  const [scheduledTime, setScheduledTime] = useState("");
  const [plannedLanes, setPlannedLanes] = useState<ScheduleDragWorkspaceState>(
    [],
  );
  const [leftLaneId, setLeftLaneId] = useState("");
  const [rightLaneId, setRightLaneId] = useState("");
  const [isProcessing, setIsProcessing] = useState(false);
  const [importBusy, setImportBusy] = useState(false);
  const [importError, setImportError] = useState<string | null>(null);
  const [importFileName, setImportFileName] = useState("");
  const [routeImportMeta, setRouteImportMeta] = useState<{
    sheetCount: number;
    rowCount: number;
  } | null>(null);
  const [stagedLines, setStagedLines] = useState<TruckLaneScheduleLineRequest[]>(
    [],
  );
  const [stagedPreviews, setStagedPreviews] = useState<
    RouteExcelSchedulePlanPreviewRow[]
  >([]);
  const [stagedPlanCounts, setStagedPlanCounts] =
    useState<RouteExcelSchedulePlanCounts | null>(null);
  const [stagedRowErrors, setStagedRowErrors] = useState<
    RouteExcelSchedulePlanError[]
  >([]);
  const [submitError, setSubmitError] = useState<string | null>(null);
  const [pendingEmptyDistrictsByLane, setPendingEmptyDistrictsByLane] =
    useState<Record<string, string[]>>({});
  const [pendingDeletes, setPendingDeletes] = useState<ScheduledDeleteSnapshot[]>(
    [],
  );

  useEffect(() => {
    if (!open) return;
    setTab("manual");
    setScheduledDate("");
    setScheduledTime("");
    setPendingEmptyDistrictsByLane({});
    setPendingDeletes([]);
    setPlannedLanes(initPlannedLanes(lanes, shops));
    const focused = defaultFocusedLaneIds(lanes);
    setLeftLaneId(focused.leftLaneId);
    setRightLaneId(focused.rightLaneId);
    setIsProcessing(false);
    setImportBusy(false);
    setImportError(null);
    setImportFileName("");
    setRouteImportMeta(null);
    setStagedLines([]);
    setStagedPreviews([]);
    setStagedPlanCounts(null);
    setStagedRowErrors([]);
    setSubmitError(null);
  }, [open, lanes, shops]);

  const modifications = useMemo(
    () => listModifications(plannedLanes),
    [plannedLanes],
  );

  const handleMoveShop = useCallback(
    (
      shopId: number,
      fromLaneId: string,
      toLaneId: string,
      beforeShopId: number | null,
      targetDistrict?: string | null,
    ) => {
      setPlannedLanes((prev) =>
        moveShop(prev, {
          shopId,
          fromLaneId,
          toLaneId,
          beforeShopId,
          targetDistrict,
        }),
      );
    },
    [],
  );

  const handleRevertShop = useCallback(
    (shopId: number, currentLaneId: string) => {
      setPlannedLanes((prev) => revertShop(prev, shopId, currentLaneId));
    },
    [],
  );

  const handleSetLoadingSequence = useCallback(
    (laneId: string, shopId: number, loadingSequence: number) => {
      setPlannedLanes((prev) =>
        setShopLoadingSequence(prev, laneId, shopId, loadingSequence),
      );
    },
    [],
  );

  const handleAddEmptyDistrict = useCallback((laneId: string, display: string) => {
    setPendingEmptyDistrictsByLane((prev) => {
      const merged = dedupeDistrictPendingOrder([...(prev[laneId] ?? []), display]);
      return { ...prev, [laneId]: merged };
    });
  }, []);

  const handleRemoveEmptyDistrict = useCallback((laneId: string, display: string) => {
    setPendingEmptyDistrictsByLane((prev) => {
      const arr = prev[laneId];
      if (!arr?.length) return prev;
      const nextArr = arr.filter((d) => d !== display);
      if (nextArr.length === arr.length) return prev;
      const next = { ...prev };
      if (nextArr.length === 0) delete next[laneId];
      else next[laneId] = nextArr;
      return next;
    });
  }, []);

  const handleDeleteShop = useCallback(
    (truckRowId: number, laneId: string) => {
      if (truckRowId <= 0) return;
      if (!window.confirm(t("confirm_schedule_removeShop"))) return;

      let snapshot: ScheduledDeleteSnapshot | null = null;
      setPlannedLanes((prev) => {
        const { next, removed, laneId: foundLaneId } = removeShopFromPlan(
          prev,
          truckRowId,
        );
        if (!removed) return prev;

        const effectiveLaneId = foundLaneId ?? laneId;
        const lane = lanes.find((l) => l.id === effectiveLaneId);
        snapshot = {
          truckRowId,
          shopCode: removed.shopCode,
          displayName: removed.displayName,
          location: formatPlannedShopLocation(removed),
          fromLaneId: effectiveLaneId,
          fromLaneLabel: lane?.label ?? effectiveLaneId,
          shop: removed,
        };
        return next;
      });
      if (snapshot) {
        setPendingDeletes((current) => {
          const without = current.filter((d) => d.truckRowId !== truckRowId);
          return [...without, snapshot!];
        });
      }
    },
    [lanes, t],
  );

  const handleRevertDelete = useCallback((truckRowId: number) => {
    setPendingDeletes((prev) => {
      const snapshot = prev.find((d) => d.truckRowId === truckRowId);
      if (!snapshot) return prev;
      setPlannedLanes((lanesState) => restoreDeletedShop(lanesState, snapshot));
      return prev.filter((d) => d.truckRowId !== truckRowId);
    });
  }, []);

  const deleteTruckRowIds = useMemo(
    () => new Set(pendingDeletes.map((d) => d.truckRowId)),
    [pendingDeletes],
  );

  const plannedSubmit = useMemo(
    () =>
      validatePlannedSubmit({
        lanes,
        shops,
        plannedLanes,
        pendingDeletes,
        date: scheduledDate,
        time: scheduledTime,
        pendingTruckRowIds,
      }),
    [
      lanes,
      shops,
      plannedLanes,
      pendingDeletes,
      scheduledDate,
      scheduledTime,
      pendingTruckRowIds,
    ],
  );

  const validationErrorTruckRowIds = useMemo(() => {
    if (plannedSubmit.ok) return new Set<number>();
    return new Set(
      plannedSubmit.errors
        .map((e) => e.truckRowId)
        .filter((id) => Number.isFinite(id) && id > 0),
    );
  }, [plannedSubmit]);

  const validationErrorsByTruckRowId = useMemo(() => {
    if (plannedSubmit.ok) return new Map<number, string>();
    const map = new Map<number, string>();
    for (const e of plannedSubmit.errors) {
      if (e.truckRowId <= 0) continue;
      map.set(
        e.truckRowId,
        formatScheduleValidationErrors(t, [e]),
      );
    }
    return map;
  }, [plannedSubmit, t]);

  const plannedValidationMessage = useMemo(() => {
    if (plannedSubmit.ok) return null;
    return formatScheduleValidationErrors(t, plannedSubmit.errors);
  }, [plannedSubmit, t]);

  const importValidation = useMemo(() => {
    const executeAt = buildExecuteAtIso(scheduledDate, scheduledTime);
    if (!executeAt || stagedLines.length === 0) return { ok: true as const };
    return validateScheduleLines({
      lines: stagedLines,
      lanes,
      pendingTruckRowIds,
      executeAt,
      shopCodeByTruckRowId: new Map(shops.map((s) => [s.truckRowId, s.shopCode])),
    });
  }, [
    scheduledDate,
    scheduledTime,
    stagedLines,
    lanes,
    pendingTruckRowIds,
    shops,
  ]);

  const buildExecuteAtIsoLocal = () => {
    if (!scheduledDate || !scheduledTime) return null;
    return `${scheduledDate}T${scheduledTime}:00`;
  };

  const handleApplyManual = async () => {
    setSubmitError(null);
    if (!plannedSubmit.ok) {
      setSubmitError(formatScheduleValidationErrors(t, plannedSubmit.errors));
      return;
    }
    setIsProcessing(true);
    try {
      await onConfirmManual({
        date: scheduledDate,
        time: scheduledTime,
        mappings: toScheduleMappings(modifications, deleteTruckRowIds),
        plannedLanes,
        pendingDeletes,
      });
      await onAfterScheduleChange?.();
      onClose();
    } catch (err: unknown) {
      setSubmitError(
        extractApiErrorMessage(err) ?? t("schedule_err_generic"),
      );
    } finally {
      setIsProcessing(false);
    }
  };

  const resolveImportRowError = useCallback(
    (err: RouteExcelSchedulePlanError) => {
      if (err.message === "invalid_departure") {
        return t("schedule_import_err_invalid_departure", { shop: err.shopCode });
      }
      if (err.message === "truck_not_found") {
        return t("schedule_import_err_truck_not_found", { shop: err.shopCode });
      }
      if (err.message === "placeholder_row") {
        return t("schedule_import_err_placeholder_row", { shop: err.shopCode });
      }
      return err.message;
    },
    [t],
  );

  const resolveActionLabel = useCallback(
    (action: string) => {
      switch (action) {
        case "MOVE":
          return t("schedule_action_move");
        case "CREATE":
          return t("schedule_action_create");
        case "DELETE":
          return t("schedule_action_delete");
        case "ENSURE_LANE":
          return t("schedule_action_ensure_lane");
        default:
          return action;
      }
    },
    [t],
  );

  const handleImportFile = async (file: File) => {
    setImportBusy(true);
    setImportError(null);
    setImportFileName(file.name);
    setRouteImportMeta(null);
    setStagedLines([]);
    setStagedPreviews([]);
    setStagedPlanCounts(null);
    setStagedRowErrors([]);
    try {
      const fd = new FormData();
      fd.append("multipartFileList", file);
      const plan = await planTruckLaneScheduleFromRouteExcelClient(fd);
      if (!plan.rowCount || plan.rowCount <= 0) {
        setImportError(t("err_importEmpty"));
        return;
      }
      setRouteImportMeta({
        sheetCount: plan.sheetCount,
        rowCount: plan.rowCount,
      });
      setStagedLines(plan.lines);
      setStagedPreviews(plan.previews);
      setStagedPlanCounts(plan.counts);
      setStagedRowErrors(plan.errors);
      if (plan.lines.length === 0) {
        setImportError(t("schedule_import_no_valid_moves"));
      }
    } catch (err: unknown) {
      const msg =
        err instanceof Error
          ? err.message
          : typeof err === "string"
            ? err
            : t("err_import");
      setImportError(msg);
    } finally {
      setImportBusy(false);
      if (importFileRef.current) importFileRef.current.value = "";
    }
  };

  const handleImportConfirm = async () => {
    const executeAt = buildExecuteAtIsoLocal();
    if (!executeAt || stagedLines.length === 0) return;
    if (!importValidation.ok) {
      setImportError(
        formatScheduleValidationErrors(t, importValidation.errors),
      );
      return;
    }
    setIsProcessing(true);
    try {
      await createTruckLaneScheduleClient({ executeAt, lines: stagedLines });
      await onAfterScheduleChange?.();
      onClose();
    } catch (err: unknown) {
      const msg =
        extractApiErrorMessage(err) ??
        (err instanceof Error
          ? err.message
          : typeof err === "string"
            ? err
            : t("err_import"));
      setImportError(msg);
    } finally {
      setIsProcessing(false);
    }
  };

  const canSubmitManual =
    !isProcessing &&
    plannedSubmit.ok &&
    (modifications.length > 0 || pendingDeletes.length > 0);

  const canSubmitImport =
    !isProcessing &&
    !importBusy &&
    scheduledDate.trim() !== "" &&
    scheduledTime.trim() !== "" &&
    stagedLines.length > 0 &&
    importValidation.ok;

  return (
    <>
      <Dialog
        open={open}
        onClose={isProcessing ? undefined : onClose}
        maxWidth="xl"
        fullWidth
        keepMounted={false}
        PaperProps={{
          sx: {
            maxHeight: "95vh",
            display: "flex",
            flexDirection: "column",
          },
        }}
      >
        <DialogTitle
          sx={{
            display: "flex",
            alignItems: "flex-start",
            justifyContent: "space-between",
            gap: 1,
            bgcolor: "grey.50",
            borderBottom: 1,
            borderColor: "divider",
            py: 1.5,
          }}
        >
          <Stack direction="row" spacing={1.5} alignItems="flex-start" sx={{ flex: 1 }}>
            <Box
              sx={{
                p: 1,
                borderRadius: 1,
                bgcolor: "primary.50",
                color: "primary.main",
                display: "flex",
              }}
            >
              <Columns size={20} />
            </Box>
            <Box sx={{ flex: 1 }}>
              <Typography variant="h6" sx={{ fontWeight: 800, lineHeight: 1.2 }}>
                {t("schedule_modal_title")}
              </Typography>
            </Box>
          </Stack>
          <IconButton
            size="small"
            onClick={onClose}
            disabled={isProcessing}
            aria-label={t("cancel")}
          >
            <X size={20} />
          </IconButton>
        </DialogTitle>

        <DialogContent
          dividers
          sx={{
            display: "flex",
            flexDirection: "column",
            gap: 3,
            overflow: "hidden",
            flex: 1,
            minHeight: 0,
          }}
        >
          <Box>
            <Typography
              variant="subtitle2"
              sx={{
                fontWeight: 700,
                mb: 1.5,
                display: "flex",
                alignItems: "center",
                gap: 0.75,
              }}
            >
              <Calendar size={16} />
              {t("schedule_step_time")}
            </Typography>
            <Stack direction={{ xs: "column", sm: "row" }} spacing={2}>
              <TextField
                label={t("schedule_exec_date")}
                type="date"
                size="small"
                fullWidth
                value={scheduledDate}
                onChange={(e) => setScheduledDate(e.target.value)}
                InputLabelProps={{ shrink: true }}
              />
              <TextField
                label={t("schedule_exec_time")}
                type="time"
                size="small"
                fullWidth
                value={scheduledTime}
                onChange={(e) => setScheduledTime(e.target.value)}
                InputLabelProps={{ shrink: true }}
              />
            </Stack>
          </Box>

          <Box
            sx={{
              flex: 1,
              minHeight: 0,
              display: "flex",
              flexDirection: "column",
              gap: 1.5,
            }}
          >
            <Typography
              variant="subtitle2"
              sx={{
                fontWeight: 700,
                display: "flex",
                alignItems: "center",
                gap: 0.75,
              }}
            >
              <ListFilter size={16} />
              {t("schedule_step_method")}
            </Typography>

            <Stack
              direction="row"
              spacing={0.5}
              sx={{ p: 0.5, bgcolor: "grey.100", borderRadius: 1, flexShrink: 0 }}
            >
              <Button
                fullWidth
                size="small"
                variant={tab === "manual" ? "contained" : "text"}
                onClick={() => setTab("manual")}
                sx={{ textTransform: "none", fontWeight: 700 }}
              >
                {t("schedule_tab_manual")}
              </Button>
              <Button
                fullWidth
                size="small"
                variant={tab === "import" ? "contained" : "text"}
                onClick={() => setTab("import")}
                sx={{ textTransform: "none", fontWeight: 700 }}
              >
                {t("schedule_tab_import")}
              </Button>
            </Stack>

            {tab === "manual" ? (
              <Stack
                direction="row"
                spacing={2}
                sx={{ flex: 1, minHeight: 0, overflow: "hidden" }}
              >
                <Box sx={{ flex: 1, minWidth: 0, minHeight: 0, display: "flex" }}>
                  <ScheduleDragWorkspacePane
                    lanes={lanes}
                    leftLaneId={leftLaneId}
                    rightLaneId={rightLaneId}
                    plannedLanes={plannedLanes}
                    pendingEmptyDistrictsByLane={pendingEmptyDistrictsByLane}
                    onLeftLaneChange={setLeftLaneId}
                    onRightLaneChange={setRightLaneId}
                    onMoveShop={handleMoveShop}
                    onRevertShop={handleRevertShop}
                    onSetLoadingSequence={handleSetLoadingSequence}
                    onAddEmptyDistrict={handleAddEmptyDistrict}
                    onRemoveEmptyDistrict={handleRemoveEmptyDistrict}
                    onDeleteShop={handleDeleteShop}
                  />
                </Box>
                <Box
                  sx={{
                    flex: "0 0 280px",
                    width: 280,
                    minWidth: 280,
                    maxWidth: 280,
                    minHeight: 0,
                    display: "flex",
                  }}
                >
                  <ScheduleReviewQueue
                    modifications={modifications}
                    pendingDeletes={pendingDeletes}
                    onRevert={handleRevertShop}
                    onRevertDelete={handleRevertDelete}
                    errorTruckRowIds={validationErrorTruckRowIds}
                    validationErrorsByTruckRowId={validationErrorsByTruckRowId}
                  />
                </Box>
              </Stack>
            ) : (
              <Stack spacing={2} sx={{ flex: 1, minHeight: 200 }}>
                <input
                  ref={importFileRef}
                  type="file"
                  accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                  style={{ display: "none" }}
                  onChange={(e) => {
                    const f = e.target.files?.[0];
                    if (f) void handleImportFile(f);
                  }}
                />
                <Box
                  sx={{
                    border: 2,
                    borderStyle: "dashed",
                    borderColor: "divider",
                    borderRadius: 2,
                    bgcolor: "grey.50",
                    p: 4,
                    textAlign: "center",
                  }}
                >
                  <Upload size={48} color="#cbd5e1" />
                  <Typography variant="subtitle2" sx={{ fontWeight: 800, mt: 2 }}>
                    {t("schedule_import_title")}
                  </Typography>
                  <Typography variant="caption" color="text.secondary" sx={{ mt: 1, display: "block" }}>
                    {t("schedule_import_hint")}
                  </Typography>
                  <Button
                    variant="outlined"
                    size="small"
                    sx={{ mt: 2 }}
                    onClick={() => importFileRef.current?.click()}
                    disabled={importBusy || isProcessing}
                    startIcon={
                      importBusy ? (
                        <CircularProgress size={14} />
                      ) : (
                        <Upload size={16} />
                      )
                    }
                  >
                    {t("schedule_import_pick")}
                  </Button>
                  {importFileName && (
                    <Typography variant="caption" sx={{ display: "block", mt: 1 }}>
                      {importFileName}
                    </Typography>
                  )}
                </Box>
                {importError && (
                  <Alert severity="error" onClose={() => setImportError(null)}>
                    {importError}
                  </Alert>
                )}
                {stagedLines.length > 0 &&
                  (!scheduledDate.trim() || !scheduledTime.trim()) && (
                    <Alert severity="info">
                      {t("schedule_import_need_datetime")}
                    </Alert>
                  )}
                {routeImportMeta && stagedLines.length > 0 && (
                  <Alert
                    severity={stagedRowErrors.length > 0 ? "warning" : "success"}
                  >
                    {t("schedule_import_plan_summary", {
                      file: importFileName || "—",
                      sheets: routeImportMeta.sheetCount,
                      rows: routeImportMeta.rowCount,
                      moves: stagedPlanCounts?.moves ?? 0,
                      creates: stagedPlanCounts?.creates ?? 0,
                      deletes: stagedPlanCounts?.deletes ?? 0,
                      ensureLanes: stagedPlanCounts?.ensureLanes ?? 0,
                      errors: stagedRowErrors.length,
                    })}
                  </Alert>
                )}
                {stagedPreviews.length > 0 && (
                  <Box
                    sx={{
                      border: 1,
                      borderColor: "divider",
                      borderRadius: 1,
                      overflow: "hidden",
                    }}
                  >
                    <Box
                      sx={{
                        display: "grid",
                        gridTemplateColumns: "88px 1fr 1fr 1.2fr 56px",
                        gap: 1,
                        px: 1.5,
                        py: 0.75,
                        bgcolor: "grey.50",
                        borderBottom: 1,
                        borderColor: "divider",
                      }}
                    >
                      <Typography variant="caption" sx={{ fontWeight: 800 }}>
                        {t("schedule_import_col_action")}
                      </Typography>
                      <Typography variant="caption" sx={{ fontWeight: 800 }}>
                        {t("schedule_import_col_shop")}
                      </Typography>
                      <Typography variant="caption" sx={{ fontWeight: 800 }}>
                        {t("schedule_import_col_name")}
                      </Typography>
                      <Typography variant="caption" sx={{ fontWeight: 800 }}>
                        {t("schedule_import_col_lane")}
                      </Typography>
                      <Typography
                        variant="caption"
                        sx={{ fontWeight: 800, textAlign: "right" }}
                      >
                        {t("schedule_import_col_seq")}
                      </Typography>
                    </Box>
                    <Box sx={{ maxHeight: 160, overflow: "auto" }}>
                      {stagedPreviews.map((row, idx) => (
                        <Box
                          key={`${row.action}-${row.truckRowId ?? idx}-${row.toTruckLanceCode}-${row.toLoadingSequence}`}
                          sx={{
                            display: "grid",
                            gridTemplateColumns: "88px 1fr 1fr 1.2fr 56px",
                            gap: 1,
                            px: 1.5,
                            py: 0.5,
                            borderBottom: 1,
                            borderColor: "divider",
                            bgcolor:
                              row.action === "DELETE"
                                ? (theme) => alpha(theme.palette.warning.main, 0.08)
                                : undefined,
                            "&:last-child": { borderBottom: 0 },
                          }}
                        >
                          <Chip
                            size="small"
                            label={resolveActionLabel(row.action)}
                            color={
                              row.action === "DELETE"
                                ? "warning"
                                : row.action === "CREATE"
                                  ? "success"
                                  : row.action === "ENSURE_LANE"
                                    ? "info"
                                    : "primary"
                            }
                            sx={{ height: 22, fontSize: "0.65rem", fontWeight: 700 }}
                          />
                          <Typography variant="caption" noWrap>
                            {row.shopCode ?? "—"}
                          </Typography>
                          <Typography variant="caption" noWrap>
                            {row.shopName ?? "—"}
                          </Typography>
                          <Typography variant="caption" noWrap>
                            {formatScheduleTargetLaneLabel(
                              row.toTruckLanceCode,
                              row.toRemark,
                            )}
                          </Typography>
                          <Typography
                            variant="caption"
                            sx={{ textAlign: "right", fontWeight: 700 }}
                          >
                            {row.toLoadingSequence ?? "—"}
                          </Typography>
                        </Box>
                      ))}
                    </Box>
                  </Box>
                )}
                {stagedRowErrors.length > 0 && (
                  <Box sx={{ maxHeight: 100, overflow: "auto" }}>
                    <Typography
                      variant="caption"
                      color="error.main"
                      sx={{ fontWeight: 700, display: "block", mb: 0.5 }}
                    >
                      {t("schedule_import_skipped_title", {
                        count: stagedRowErrors.length,
                      })}
                    </Typography>
                    {stagedRowErrors.map((e, i) => (
                      <Typography
                        key={`${e.shopCode}-${i}`}
                        variant="caption"
                        display="block"
                        color="text.secondary"
                      >
                        {t("schedule_import_row_error", {
                          shop: e.shopCode,
                          name: e.shopName,
                          reason: resolveImportRowError(e),
                        })}
                      </Typography>
                    ))}
                  </Box>
                )}
              </Stack>
            )}
          </Box>

          {(submitError || plannedValidationMessage) && (
            <Alert
              severity="error"
              onClose={
                submitError
                  ? () => setSubmitError(null)
                  : undefined
              }
            >
              {submitError ?? plannedValidationMessage}
            </Alert>
          )}

          {tab === "manual" &&
            (modifications.length > 0 || pendingDeletes.length > 0) && (
            <Alert
              severity="warning"
              icon={<AlertCircle size={20} />}
              sx={{
                bgcolor: alpha("#ed6c02", 0.08),
                border: 1,
                borderColor: "warning.light",
              }}
            >
              <Typography variant="body2" sx={{ fontWeight: 800 }}>
                {t("schedule_summary_changes", {
                  count: modifications.length + pendingDeletes.length,
                })}
              </Typography>
              {scheduledDate && scheduledTime && (
                <Typography variant="caption" color="text.secondary">
                  {t("schedule_planned_label")}: {scheduledDate} {scheduledTime}
                </Typography>
              )}
            </Alert>
          )}
        </DialogContent>

        <DialogActions sx={{ px: 2, py: 1.5, bgcolor: "grey.50" }}>
          <Button onClick={onClose} disabled={isProcessing}>
            {t("cancel")}
          </Button>
          {tab === "manual" ? (
            <Button
              variant="contained"
              disabled={!canSubmitManual}
              onClick={() => void handleApplyManual()}
              startIcon={
                isProcessing ? (
                  <CircularProgress size={16} color="inherit" />
                ) : (
                  <Save size={18} />
                )
              }
              sx={{ fontWeight: 800 }}
            >
              {t("schedule_confirm_btn")}
            </Button>
          ) : (
            <Button
              variant="contained"
              disabled={!canSubmitImport}
              onClick={() => void handleImportConfirm()}
              startIcon={
                isProcessing ? (
                  <CircularProgress size={16} color="inherit" />
                ) : (
                  <Save size={18} />
                )
              }
              sx={{ fontWeight: 800 }}
            >
              {t("schedule_import_confirm_btn")}
            </Button>
          )}
        </DialogActions>
      </Dialog>
    </>
  );
};

export default memo(ScheduleChangeModal);
