"use client";

import {
  Box,
  Button,
  Chip,
  CircularProgress,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  MobileStepper,
  Paper,
  Stack,
  TextField,
  Typography,
} from "@mui/material";
import { KeyboardArrowLeft, KeyboardArrowRight } from "@mui/icons-material";
import dayjs from "dayjs";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import Swal from "sweetalert2";
import {
  fetchWorkbenchMergeTicketCandidates,
  mergeWorkbenchTickets,
  type WorkbenchMergeTicketCandidate,
} from "@/app/api/doworkbench/actions";
import { isWorkbenchMergeTicketNo } from "@/utils/workbenchReleaseType";

const SWAL_ABOVE_DIALOG = {
  customClass: { container: "swal2-custom-zindex" },
} as const;

type Props = {
  open: boolean;
  onClose: () => void;
  /** YYYY-MM-DD when dialog opens (from Etra tab date). */
  initialDateYmd: string;
  onMerged?: () => void;
};

function floorLabel(storeId: string | null | undefined, t: (k: string) => string): string {
  const s = (storeId ?? "").trim().replace(/\//g, "").toUpperCase();
  if (s === "2F") return "2/F";
  if (s === "4F") return "4/F";
  if (!s) return t("Truck X");
  return storeId ?? "";
}

function shopPrimary(c: WorkbenchMergeTicketCandidate, t: (k: string) => string): string {
  const code = (c.shopCode ?? "").trim();
  const name = (c.shopName ?? "").trim();
  if (code && name && code !== name) return `${code} · ${name}`;
  return name || code || t("Shop");
}

function laneSecondary(c: WorkbenchMergeTicketCandidate, t: (k: string) => string): string {
  const dep = (c.truckDepartureTime ?? "").trim();
  const lane = (c.truckLanceCode ?? "").trim();
  const floor = floorLabel(c.storeId, t);
  const is4F = (c.storeId ?? "").trim().replace(/\//g, "").toUpperCase() === "4F";
  const seq =
    is4F && c.loadingSequence != null
      ? `${t("Loading sequence")} ${c.loadingSequence} · `
      : "";
  return `${seq}${dep ? `${dep} ` : ""}${lane} (${floor})`;
}

type CarouselProps = {
  title: string;
  items: WorkbenchMergeTicketCandidate[];
  selectedId: number | null;
  onSelect: (id: number) => void;
  emptyText: string;
  accent: "primary" | "secondary";
};

const MERGE_TICKETS_PER_PAGE = 3;

function MergeTicketCard({
  ticket,
  selected,
  accent,
  onSelect,
}: {
  ticket: WorkbenchMergeTicketCandidate;
  selected: boolean;
  accent: "primary" | "secondary";
  onSelect: (id: number) => void;
}) {
  const { t } = useTranslation("pickOrder");
  return (
    <Paper
      variant="outlined"
      onClick={() => onSelect(ticket.id)}
      sx={{
        p: 1.5,
        cursor: "pointer",
        borderWidth: selected ? 2 : 1,
        borderColor: selected ? `${accent}.main` : "divider",
        bgcolor: "background.paper",
      }}
    >
      <Stack spacing={0.75}>
        <Stack direction="row" spacing={1} alignItems="center" flexWrap="wrap">
          <Typography variant="subtitle2" sx={{ fontWeight: 700, wordBreak: "break-all" }}>
            {ticket.ticketNo ?? `#${ticket.id}`}
          </Typography>
          <Chip
            size="small"
            label={t(ticket.releaseType ?? "").trim() || "—"}
            color={accent}
            variant="outlined"
          />
          <Chip size="small" label={floorLabel(ticket.storeId, t)} variant="outlined" />
        </Stack>
        <Typography variant="body2" sx={{ fontWeight: 600 }}>
          {shopPrimary(ticket, t)}
        </Typography>
        <Typography variant="caption" color="text.secondary">
          {laneSecondary(ticket, t)}
        </Typography>
        <Typography variant="caption" color="text.secondary" sx={{ wordBreak: "break-all" }}>
          {ticket.deliveryOrderCodes.length > 0
            ? `${t("Delivery Order Code")}: ${ticket.deliveryOrderCodes.join(", ")}`
            : t("No delivery orders on ticket")}
        </Typography>
      </Stack>
    </Paper>
  );
}

function MergeTicketCarousel({
  title,
  items,
  selectedId,
  onSelect,
  emptyText,
  accent,
}: CarouselProps) {
  const { t } = useTranslation("pickOrder");
  const [page, setPage] = useState(0);

  const pageCount = Math.max(1, Math.ceil(items.length / MERGE_TICKETS_PER_PAGE));

  const pageItems = useMemo(() => {
    const start = page * MERGE_TICKETS_PER_PAGE;
    return items.slice(start, start + MERGE_TICKETS_PER_PAGE);
  }, [items, page]);

  useEffect(() => {
    setPage(0);
  }, [items]);

  useEffect(() => {
    if (items.length === 0 || selectedId == null) return;
    const idx = items.findIndex((x) => x.id === selectedId);
    if (idx >= 0) setPage(Math.floor(idx / MERGE_TICKETS_PER_PAGE));
  }, [selectedId, items]);

  useEffect(() => {
    if (page > pageCount - 1) setPage(Math.max(0, pageCount - 1));
  }, [page, pageCount]);

  return (
    <Box sx={{ flex: 1, minWidth: 0 }}>
      <Typography variant="subtitle2" sx={{ fontWeight: 700, mb: 1 }}>
        {title}
      </Typography>
      {items.length === 0 ? (
        <Paper variant="outlined" sx={{ p: 2, minHeight: 160, display: "flex", alignItems: "center" }}>
          <Typography variant="body2" color="text.secondary">
            {emptyText}
          </Typography>
        </Paper>
      ) : (
        <>
          <Stack spacing={1} sx={{ minHeight: 160 }}>
            {pageItems.map((ticket) => (
              <MergeTicketCard
                key={ticket.id}
                ticket={ticket}
                selected={selectedId === ticket.id}
                accent={accent}
                onSelect={onSelect}
              />
            ))}
          </Stack>
          {pageCount > 1 && (
            <>
              <MobileStepper
                variant="dots"
                steps={pageCount}
                position="static"
                activeStep={page}
                sx={{ mt: 0.5, bgcolor: "transparent", px: 0 }}
                nextButton={
                  <Button
                    size="small"
                    disabled={page >= pageCount - 1}
                    onClick={() => setPage((p) => Math.min(p + 1, pageCount - 1))}
                  >
                    {t("Next")}
                    <KeyboardArrowRight />
                  </Button>
                }
                backButton={
                  <Button
                    size="small"
                    disabled={page <= 0}
                    onClick={() => setPage((p) => Math.max(p - 1, 0))}
                  >
                    <KeyboardArrowLeft />
                    {t("Back")}
                  </Button>
                }
              />
              <Typography variant="caption" color="text.secondary" sx={{ display: "block", textAlign: "center" }}>
                {page + 1} / {pageCount}
              </Typography>
            </>
          )}
        </>
      )}
    </Box>
  );
}

const WorkbenchEtraMergeDialog: React.FC<Props> = ({
  open,
  onClose,
  initialDateYmd,
  onMerged,
}) => {
  const { t } = useTranslation("pickOrder");
  const [shopSearch, setShopSearch] = useState("");
  const [requiredDate, setRequiredDate] = useState(initialDateYmd);
  const [loading, setLoading] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [batchTickets, setBatchTickets] = useState<WorkbenchMergeTicketCandidate[]>([]);
  const [extraTickets, setExtraTickets] = useState<WorkbenchMergeTicketCandidate[]>([]);
  const [selectedBatchId, setSelectedBatchId] = useState<number | null>(null);
  const [selectedExtraId, setSelectedExtraId] = useState<number | null>(null);
  const [hasSearched, setHasSearched] = useState(false);

  const selectedBatch = useMemo(
    () => batchTickets.find((x) => x.id === selectedBatchId) ?? null,
    [batchTickets, selectedBatchId],
  );

  const filteredExtraTickets = useMemo(() => {
    if (!selectedBatch) return [];
    return extraTickets.filter((x) => x.laneKey === selectedBatch.laneKey);
  }, [extraTickets, selectedBatch]);

  const loadCandidates = useCallback(async () => {
    setLoading(true);
    try {
      const data = await fetchWorkbenchMergeTicketCandidates({
        requiredDate,
        shopSearch: shopSearch.trim() || undefined,
      });
      setBatchTickets(data.batchFamilyTickets);
      setExtraTickets(data.isExtraTickets);
      setSelectedBatchId(null);
      setSelectedExtraId(null);
      setHasSearched(true);
    } catch (e) {
      console.error("fetchWorkbenchMergeTicketCandidates:", e);
      setBatchTickets([]);
      setExtraTickets([]);
      setHasSearched(true);
      await Swal.fire({
        ...SWAL_ABOVE_DIALOG,
        icon: "error",
        title: t("Error"),
        text: e instanceof Error ? e.message : t("Merge Etra ticket search failed"),
      });
    } finally {
      setLoading(false);
    }
  }, [requiredDate, shopSearch]);

  useEffect(() => {
    if (!open) return;
    setRequiredDate(initialDateYmd);
    setShopSearch("");
    setSelectedBatchId(null);
    setSelectedExtraId(null);
    setBatchTickets([]);
    setExtraTickets([]);
    setHasSearched(false);
  }, [open, initialDateYmd]);

  useEffect(() => {
    if (selectedExtraId == null) return;
    if (!filteredExtraTickets.some((x) => x.id === selectedExtraId)) {
      setSelectedExtraId(null);
    }
  }, [filteredExtraTickets, selectedExtraId]);

  const canConfirm = selectedBatchId != null && selectedExtraId != null && !submitting;

  const handleConfirm = async () => {
    if (!canConfirm || selectedBatchId == null || selectedExtraId == null) return;
    const batch = batchTickets.find((x) => x.id === selectedBatchId);
    const extra = filteredExtraTickets.find((x) => x.id === selectedExtraId);
    if (!batch || !extra) return;

    const intoExistingTiM = isWorkbenchMergeTicketNo(batch.ticketNo);
    const leftLabel = intoExistingTiM ? t("Merge ticket TI-M") : t("Batch/Single ticket");
    const confirmHint = intoExistingTiM
      ? t("Merge Etra ticket confirm hint into TI-M")
      : t("Merge Etra ticket confirm hint");

    const confirm = await Swal.fire({
      ...SWAL_ABOVE_DIALOG,
      icon: "question",
      title: t("Merge Etra ticket confirm title"),
      html: `
        <div style="text-align:left;font-size:0.95em;">
          <p><b>${leftLabel}:</b> ${batch.ticketNo ?? batch.id}</p>
          <p><b>${t("Etra ticket")}:</b> ${extra.ticketNo ?? extra.id}</p>
          <p style="margin-top:0.75em;color:#666;">${confirmHint}</p>
        </div>
      `,
      showCancelButton: true,
      confirmButtonText: t("Confirm"),
      cancelButtonText: t("Cancel"),
      confirmButtonColor: "#8dba00",
      cancelButtonColor: "#F04438",
    });
    if (!confirm.isConfirmed) return;

    setSubmitting(true);
    try {
      const res = await mergeWorkbenchTickets({
        batchOrSingleDopoId: selectedBatchId,
        isExtraDopoId: selectedExtraId,
      });
      if ((res.code ?? "").toUpperCase() !== "SUCCESS") {
        await Swal.fire({
          ...SWAL_ABOVE_DIALOG,
          icon: "error",
          title: t("Error"),
          text: res.message ?? t("Merge Etra ticket failed"),
        });
        return;
      }
      await Swal.fire({
        ...SWAL_ABOVE_DIALOG,
        icon: "success",
        title: t("Merge Etra ticket success"),
      });
      onMerged?.();
      onClose();
    } catch (e) {
      console.error("mergeWorkbenchTickets:", e);
      await Swal.fire({
        ...SWAL_ABOVE_DIALOG,
        icon: "error",
        title: t("Error"),
        text: t("Merge Etra ticket failed"),
      });
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Dialog open={open} onClose={onClose} maxWidth="md" fullWidth>
      <DialogTitle>{t("Merge Etra ticket dialog title")}</DialogTitle>
      <DialogContent>
        <Stack spacing={2} sx={{ pt: 0.5 }}>
          <Stack direction={{ xs: "column", sm: "row" }} spacing={2} alignItems={{ sm: "flex-end" }}>
            <TextField
              size="small"
              fullWidth
              label={t("Shop search")}
              value={shopSearch}
              onChange={(e) => setShopSearch(e.target.value)}
              placeholder={t("Shop Name")}
              disabled={loading}
            />
            <TextField
              size="small"
              type="date"
              label={t("Required Date")}
              value={requiredDate}
              onChange={(e) => setRequiredDate(e.target.value || dayjs().format("YYYY-MM-DD"))}
              InputLabelProps={{ shrink: true }}
              sx={{ minWidth: 160 }}
              disabled={loading}
            />
            <Button
              variant="contained"
              onClick={() => void loadCandidates()}
              disabled={loading}
              sx={{ minWidth: 100, flexShrink: 0 }}
            >
              {loading ? t("Loading...") : t("Confirm Search")}
            </Button>
          </Stack>

          <Typography variant="caption" color="text.secondary">
            {t("Merge Etra ticket lane hint")}
          </Typography>

          {loading ? (
            <Box sx={{ display: "flex", justifyContent: "center", py: 4 }}>
              <CircularProgress size={32} />
            </Box>
          ) : (
            <Stack direction={{ xs: "column", md: "row" }} spacing={2}>
              <MergeTicketCarousel
                title={t("Merge left column title")}
                items={batchTickets}
                selectedId={selectedBatchId}
                onSelect={(id) => {
                  setSelectedBatchId(id);
                  setSelectedExtraId(null);
                }}
                emptyText={
                  !hasSearched
                    ? t("Merge Etra ticket search prompt")
                    : t("No mergeable batch tickets")
                }
                accent="primary"
              />
              <MergeTicketCarousel
                title={t("Etra ticket")}
                items={filteredExtraTickets}
                selectedId={selectedExtraId}
                onSelect={setSelectedExtraId}
                emptyText={
                  !hasSearched
                    ? t("Merge Etra ticket search prompt")
                    : selectedBatch
                      ? t("No isExtra on same lane")
                      : t("Select batch ticket first for isExtra")
                }
                accent="secondary"
              />
            </Stack>
          )}
        </Stack>
      </DialogContent>
      <DialogActions sx={{ px: 3, pb: 2 }}>
        <Button onClick={onClose} disabled={submitting}>
          {t("Cancel")}
        </Button>
        <Button variant="contained" color="secondary" disabled={!canConfirm} onClick={() => void handleConfirm()}>
          {submitting ? t("Loading...") : t("Merge Etra ticket confirm")}
        </Button>
      </DialogActions>
    </Dialog>
  );
};

export default WorkbenchEtraMergeDialog;
