import { Icon } from "@iconify/react";
import {
  Alert,
  Autocomplete,
  Box,
  Button,
  Chip,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  Divider,
  Grid,
  MenuItem,
  Paper,
  Stack,
  TextField,
  Typography,
} from "@mui/material";
import { useQuery } from "@tanstack/react-query";
import { useEffect, useMemo, useState } from "react";
import { getMediosPagoActivos } from "../../../api/pagos.service";
import { getTesCuentas } from "../../../api/tes.service";
import { fmtMoneda } from "../../_standards/enums/monedas";
import { BancoSelect } from "../../_standards";
import { useCerrarRendicionMutation } from "../../../tanstack/RendicionViaticosStack";
import { useConfirmDialog } from "../../../hooks/useConfirmDialog";
import { hoyISO } from "../../../utils/fecha";

const TODAY = () => hoyISO();

/**
 * Cierra una rendición.
 * Muestra el saldo calculado y pide los datos del cierre según sea:
 *   - Saldo = 0 → sin datos extra.
 *   - Saldo > 0 (funcionario devuelve) → cuenta destino + medio de pago.
 *   - Saldo < 0 (empresa reintegra) → elegir modo INMEDIATO o DIFERIDO;
 *     si INMEDIATO, cuenta origen + medio de pago.
 *
 * Ver docs/plan-rendicion-viaticos.md — Fase 3.
 */
export function CerrarRendicionDialog({ open, onClose, rendicion, defaultReintegro = "INMEDIATO" }) {
  const [fechaCierre, setFechaCierre] = useState(TODAY());
  const [tipoReintegro, setTipoReintegro] = useState(defaultReintegro);
  const [medioPagoId, setMedioPagoId] = useState("");
  const [tesCuentaId, setTesCuentaId] = useState("");
  const [numeroOperacion, setNumeroOperacion] = useState("");
  const [observaciones, setObservaciones] = useState("");
  // Datos de cheque
  const [numeroCheque, setNumeroCheque] = useState("");
  const [bancoEmisor, setBancoEmisor] = useState("");
  const [titularCheque, setTitularCheque] = useState("");
  const [fechaEmisionCheque, setFechaEmisionCheque] = useState(TODAY());
  const [fechaVencCheque, setFechaVencCheque] = useState(TODAY());
  const [errors, setErrors] = useState([]);

  const mut = useCerrarRendicionMutation();
  const { confirm, dialogs: confirmDialogs } = useConfirmDialog();
  const monedaCodigo = rendicion?.moneda?.codigo || "PYG";
  const saldo = Number(rendicion?.saldo || 0);
  const monto = Math.abs(saldo);
  const modo = useMemo(() => {
    if (Math.abs(saldo) < 0.001) return "SIN_SALDO";
    return saldo > 0 ? "DEVOLUCION" : "REINTEGRO";
  }, [saldo]);

  const { data: mediosPago = [] } = useQuery({
    queryKey: ["medios-pago-cerrar-rendicion"],
    queryFn: getMediosPagoActivos,
    enabled: open,
    staleTime: 5 * 60 * 1000,
  });
  const { data: tesCuentasResp } = useQuery({
    queryKey: ["tes-cuentas-cerrar-rendicion"],
    queryFn: () => getTesCuentas({ activo: true }),
    enabled: open,
    staleTime: 5 * 60 * 1000,
  });
  const tesCuentas = tesCuentasResp?.items ?? tesCuentasResp ?? [];

  useEffect(() => {
    if (open) {
      setFechaCierre(TODAY());
      setTipoReintegro(defaultReintegro);
      setMedioPagoId("");
      setTesCuentaId("");
      setNumeroOperacion("");
      setObservaciones("");
      setNumeroCheque("");
      setBancoEmisor("");
      setTitularCheque("");
      setFechaEmisionCheque(TODAY());
      setFechaVencCheque(TODAY());
      setErrors([]);
    }
  }, [open, defaultReintegro]);

  const requiereCuentaYMedio =
    modo === "DEVOLUCION" || (modo === "REINTEGRO" && tipoReintegro === "INMEDIATO");

  const medioPagoSel = mediosPago.find((m) => m.id === medioPagoId);
  const esCheque = useMemo(() => {
    if (!requiereCuentaYMedio || !medioPagoSel) return false;
    const codigo = Number(medioPagoSel.codigo ?? 0);
    const desc = (medioPagoSel.descripcion ?? "").toLowerCase();
    return codigo === 2 || desc.includes("cheque");
  }, [requiereCuentaYMedio, medioPagoSel]);
  const esEfectivo = useMemo(() => {
    if (!requiereCuentaYMedio || !medioPagoSel) return false;
    const codigo = Number(medioPagoSel.codigo ?? 0);
    const desc = (medioPagoSel.descripcion ?? "").toLowerCase();
    return codigo === 1 || desc.includes("efectivo") || desc.includes("contado");
  }, [requiereCuentaYMedio, medioPagoSel]);
  const tesCuentasFiltradas = esEfectivo
    ? tesCuentas.filter((c) => ["CAJA_CHICA", "FONDO_FIJO", "BILLETERA"].includes(c.tipo))
    : tesCuentas;

  const validate = () => {
    const errs = [];
    if (!fechaCierre) errs.push("Cargá la fecha del cierre.");
    if (requiereCuentaYMedio) {
      if (!tesCuentaId) errs.push("Elegí la cuenta de tesorería.");
      if (!medioPagoId) errs.push("Elegí el medio de pago.");
      if (esCheque) {
        if (!numeroCheque.trim()) errs.push("Nº de cheque requerido.");
        if (!bancoEmisor.trim()) errs.push("Banco emisor requerido.");
        if (!titularCheque.trim()) errs.push("Titular del cheque requerido.");
        if (!fechaEmisionCheque) errs.push("Fecha de emisión requerida.");
        if (!fechaVencCheque) errs.push("Fecha de cobro / vencimiento requerida.");
      }
    }
    setErrors(errs);
    return errs.length === 0;
  };

  const buildResumen = () => {
    const medioNombre = mediosPago.find((m) => m.id === medioPagoId)?.descripcion || "—";
    const cuentaNombre = tesCuentas.find((c) => c.id === tesCuentaId)?.nombre || "—";
    const filas = [
      ["Rendición", rendicion?.numero_rendicion || "—"],
      ["Adelantado", fmtMoneda(Number(rendicion?.monto_adelanto_total || 0), monedaCodigo)],
      ["Rendido", fmtMoneda(Number(rendicion?.monto_rendido_total || 0), monedaCodigo)],
      [
        "Saldo",
        modo === "SIN_SALDO"
          ? "Sin saldo"
          : `${fmtMoneda(monto, monedaCodigo)} ${modo === "DEVOLUCION" ? "(el empleado devuelve)" : "(la empresa reintegra)"}`,
      ],
      ["Fecha cierre", fechaCierre],
    ];
    if (modo === "REINTEGRO") {
      filas.push(["Modo reintegro", tipoReintegro === "INMEDIATO" ? "Inmediato" : "Diferido (CxP)"]);
    }
    if (requiereCuentaYMedio) {
      filas.push(["Medio de pago", medioNombre], ["Cuenta", cuentaNombre]);
      if (numeroOperacion) filas.push(["Nº operación", numeroOperacion]);
    }

    return (
      <Box>
        <Typography variant="body2" sx={{ mb: 1.5 }}>
          Se cerrará la rendición y {modo === "SIN_SALDO"
            ? "quedará marcada como completada."
            : modo === "DEVOLUCION"
              ? "se registrará el ingreso a tesorería + asiento de la devolución."
              : tipoReintegro === "INMEDIATO"
                ? "se ejecutará el egreso de tesorería + asiento del reintegro."
                : "se generará una CxP al empleado + asiento del reintegro diferido."}
        </Typography>
        <Box sx={{ display: "grid", gridTemplateColumns: "auto 1fr", columnGap: 2, rowGap: 0.5 }}>
          {filas.map(([k, v]) => (
            <Box key={k} sx={{ display: "contents" }}>
              <Typography variant="caption" color="text.secondary">
                {k}
              </Typography>
              <Typography variant="body2" fontWeight={600}>
                {v}
              </Typography>
            </Box>
          ))}
        </Box>
        <Typography variant="caption" color="warning.main" sx={{ display: "block", mt: 1.5 }}>
          Una vez cerrada, la rendición es inmutable. Para corregir hay que anular todo.
        </Typography>
      </Box>
    );
  };

  const handleSubmit = async () => {
    if (!validate()) return;

    const ok = await confirm({
      title: "Confirmar cierre de rendición",
      message: buildResumen(),
      confirmText: "Cerrar rendición",
      cancelText: "Revisar",
      confirmColor: "primary",
      maxWidth: "sm",
    });
    if (!ok) return;

    const dto = {
      fecha_cierre: fechaCierre,
      observaciones: observaciones || undefined,
    };
    if (modo === "REINTEGRO") dto.tipo_reintegro = tipoReintegro;
    if (requiereCuentaYMedio) {
      dto.tes_cuenta_id = tesCuentaId;
      dto.medio_pago_id = medioPagoId;
      dto.numero_operacion = esEfectivo ? undefined : numeroOperacion || undefined;
      if (esCheque) {
        dto.numero_cheque = numeroCheque.trim();
        dto.banco_emisor = bancoEmisor.trim();
        dto.titular_cheque = titularCheque.trim();
        dto.fecha_emision_cheque = fechaEmisionCheque;
        dto.fecha_vencimiento_cheque = fechaVencCheque;
      }
    }
    try {
      await mut.mutateAsync({ id: rendicion.id, dto });
      onClose?.();
    } catch {
      /* toast por hook */
    }
  };

  const colorSaldo =
    modo === "SIN_SALDO" ? "success.main" : modo === "DEVOLUCION" ? "warning.main" : "error.main";

  return (
    <Dialog open={open} onClose={mut.isPending ? undefined : onClose} maxWidth="md" fullWidth>
      <form onSubmit={(e) => { e.preventDefault(); handleSubmit(); }}>
        <DialogTitle sx={{ display: "flex", alignItems: "center", gap: 1 }}>
          <Icon icon="mdi:check-circle-outline" />
          Cerrar rendición
          <Chip
            size="small"
            variant="outlined"
            color={rendicion?.numero_rendicion ? "primary" : "default"}
            label={rendicion?.numero_rendicion}
            sx={{ ml: 1, fontFamily: "monospace" }}
          />
        </DialogTitle>
        <DialogContent dividers>
          {errors.length > 0 && (
            <Alert severity="error" sx={{ mb: 2 }}>
              <Typography variant="body2" fontWeight={600} sx={{ mb: 0.5 }}>
                Corregí lo siguiente:
              </Typography>
              <ul style={{ margin: 0, paddingLeft: 20 }}>
                {errors.map((e, i) => (
                  <li key={i}>{e}</li>
                ))}
              </ul>
            </Alert>
          )}

          {/* Resumen de saldo */}
          <Paper variant="outlined" sx={{ p: 2, mb: 2, borderRadius: 1.5 }}>
            <Grid container spacing={2}>
              <Grid size={{ xs: 4 }}>
                <Typography variant="caption" color="text.secondary">
                  Adelantado
                </Typography>
                <Typography variant="h6" fontWeight={700} color="info.main">
                  {fmtMoneda(Number(rendicion?.monto_adelanto_total || 0), monedaCodigo)}
                </Typography>
              </Grid>
              <Grid size={{ xs: 4 }}>
                <Typography variant="caption" color="text.secondary">
                  Rendido
                </Typography>
                <Typography variant="h6" fontWeight={700} color="primary.main">
                  {fmtMoneda(Number(rendicion?.monto_rendido_total || 0), monedaCodigo)}
                </Typography>
              </Grid>
              <Grid size={{ xs: 4 }}>
                <Typography variant="caption" color="text.secondary">
                  Saldo
                </Typography>
                <Typography variant="h5" fontWeight={700} sx={{ color: colorSaldo }}>
                  {fmtMoneda(saldo, monedaCodigo)}
                </Typography>
              </Grid>
            </Grid>
            <Divider sx={{ my: 1.5 }} />
            {modo === "SIN_SALDO" && (
              <Alert severity="success" icon={<Icon icon="mdi:check" />}>
                <strong>Saldo balanceado.</strong> Al cerrar no se generará ningún movimiento
                adicional — solo se marca la rendición como CERRADA.
              </Alert>
            )}
            {modo === "DEVOLUCION" && (
              <Alert severity="warning" icon={<Icon icon="mdi:cash-refund" />}>
                <strong>Devolución del empleado:</strong> Debe entregar{" "}
                <strong>{fmtMoneda(monto, monedaCodigo)}</strong> a la empresa. Elegí a qué cuenta
                de tesorería ingresa.
              </Alert>
            )}
            {modo === "REINTEGRO" && (
              <Alert severity="error" icon={<Icon icon="mdi:cash-fast" />}>
                <strong>Reintegro al empleado:</strong> La empresa le debe{" "}
                <strong>{fmtMoneda(monto, monedaCodigo)}</strong>. Elegí si pagar ahora o dejarlo
                como cuenta por pagar al empleado.
              </Alert>
            )}
          </Paper>

          {/* Modo reintegro (solo si saldo negativo) */}
          {modo === "REINTEGRO" && (
            <Paper variant="outlined" sx={{ p: 2, bgcolor: "action.hover", borderRadius: 1.5, mb: 2 }}>
              <Box sx={{ display: "flex", alignItems: "center", gap: 1, mb: 1.5 }}>
                <Icon icon="mdi:timer-outline" width={18} />
                <Typography variant="caption" fontWeight={700} sx={{ letterSpacing: 0.5, color: "text.secondary" }}>
                  MODO DE REINTEGRO
                </Typography>
              </Box>
              <Stack direction={{ xs: "column", sm: "row" }} spacing={2}>
                {[
                  {
                    key: "INMEDIATO",
                    icon: "mdi:flash",
                    title: "Pagar ahora",
                    desc: "Genera un movimiento de tesorería EGRESO + asiento contable. Requiere que la cuenta origen tenga saldo.",
                  },
                  {
                    key: "DIFERIDO",
                    icon: "mdi:clock-outline",
                    title: "Diferir (CxP al empleado)",
                    desc: "Genera una cuenta por pagar al empleado. Se paga después junto con el sueldo o manualmente desde caja.",
                  },
                ].map((opt) => {
                  const selected = tipoReintegro === opt.key;
                  return (
                    <Paper
                      key={opt.key}
                      variant="outlined"
                      onClick={() => setTipoReintegro(opt.key)}
                      sx={{
                        p: 2,
                        flex: 1,
                        cursor: "pointer",
                        borderColor: selected ? "primary.main" : "divider",
                        borderWidth: selected ? 2 : 1,
                        bgcolor: selected
                          ? (t) =>
                              t.palette.mode === "dark"
                                ? "rgba(99,102,241,0.16)"
                                : "rgba(99,102,241,0.08)"
                          : "transparent",
                        opacity: selected ? 1 : 0.75,
                        transition: "all 0.15s",
                        "&:hover": { opacity: 1, borderColor: "primary.main" },
                      }}
                    >
                      <Stack direction="row" spacing={1} alignItems="center" mb={1}>
                        <Icon
                          icon={opt.icon}
                          width={20}
                          color={selected ? "var(--mui-palette-primary-main)" : undefined}
                        />
                        <Typography
                          variant="body2"
                          fontWeight={700}
                          color={selected ? "primary.main" : "text.primary"}
                        >
                          {opt.title}
                        </Typography>
                      </Stack>
                      <Typography
                        variant="caption"
                        sx={{
                          color: selected ? "text.primary" : "text.secondary",
                          display: "block",
                          lineHeight: 1.4,
                        }}
                      >
                        {opt.desc}
                      </Typography>
                    </Paper>
                  );
                })}
              </Stack>
            </Paper>
          )}

          {/* Datos del pago (solo si aplica) */}
          {requiereCuentaYMedio && (
            <Paper variant="outlined" sx={{ p: 2, bgcolor: "action.hover", borderRadius: 1.5 }}>
              <Box sx={{ display: "flex", alignItems: "center", gap: 1, mb: 1.5 }}>
                <Icon icon="mdi:bank-outline" width={18} />
                <Typography variant="caption" fontWeight={700} sx={{ letterSpacing: 0.5, color: "text.secondary" }}>
                  {modo === "DEVOLUCION" ? "CUENTA DESTINO (INGRESA)" : "CUENTA ORIGEN (EGRESA)"}
                </Typography>
              </Box>
              <Grid container spacing={2}>
                <Grid size={{ xs: 12, sm: 6 }}>
                  <Autocomplete
                    size="small"
                    options={tesCuentasFiltradas}
                    value={tesCuentasFiltradas.find((c) => c.id === tesCuentaId) || null}
                    onChange={(_, v) => setTesCuentaId(v?.id ?? "")}
                    getOptionLabel={(o) => (o ? `${o.nombre} (${o.moneda})` : "")}
                    isOptionEqualToValue={(o, v) => o?.id === v?.id}
                    renderInput={(params) => (
                      <TextField
                        {...params}
                        label={
                          esEfectivo
                            ? "Caja *"
                            : modo === "DEVOLUCION"
                              ? "Cuenta destino *"
                              : "Cuenta origen *"
                        }
                      />
                    )}
                  />
                </Grid>
                <Grid size={{ xs: 12, sm: 6 }}>
                  <TextField
                    select
                    size="small"
                    fullWidth
                    label="Medio de pago *"
                    value={medioPagoId}
                    onChange={(e) => setMedioPagoId(e.target.value)}
                  >
                    {mediosPago.map((m) => (
                      <MenuItem key={m.id} value={m.id}>
                        {m.descripcion}
                      </MenuItem>
                    ))}
                  </TextField>
                </Grid>
                {!esEfectivo && (
                  <Grid size={{ xs: 12, sm: 6 }}>
                    <TextField
                      size="small"
                      fullWidth
                      label="N° operación (opcional)"
                      placeholder="Ej: TRF-987654"
                      value={numeroOperacion}
                      onChange={(e) => setNumeroOperacion(e.target.value)}
                    />
                  </Grid>
                )}
                <Grid size={{ xs: 12, sm: 6 }}>
                  <TextField
                    size="small"
                    fullWidth
                    type="date"
                    label="Fecha del cierre *"
                    InputLabelProps={{ shrink: true }}
                    value={fechaCierre}
                    onChange={(e) => setFechaCierre(e.target.value)}
                  />
                </Grid>

                {esCheque && (
                  <>
                    <Grid size={12}>
                      <Box
                        sx={{
                          display: "flex",
                          alignItems: "center",
                          gap: 1,
                          mt: 1,
                          pb: 0.5,
                          borderBottom: (t) => `1px dashed ${t.palette.divider}`,
                        }}
                      >
                        <Icon icon="mdi:checkbook" />
                        <Typography variant="caption" fontWeight={700} sx={{ letterSpacing: 0.5, color: "text.secondary" }}>
                          DATOS DEL CHEQUE
                        </Typography>
                      </Box>
                    </Grid>
                    <Grid size={{ xs: 12, sm: 6 }}>
                      <TextField
                        size="small"
                        fullWidth
                        label="Nº cheque *"
                        placeholder="Ej: 0012345"
                        value={numeroCheque}
                        onChange={(e) => setNumeroCheque(e.target.value)}
                      />
                    </Grid>
                    <Grid size={{ xs: 12, sm: 6 }}>
                      <BancoSelect
                        label="Banco emisor *"
                        value={bancoEmisor}
                        onChange={setBancoEmisor}
                      />
                    </Grid>
                    <Grid size={{ xs: 12, sm: 6 }}>
                      <TextField
                        size="small"
                        fullWidth
                        label="Titular *"
                        placeholder="Nombre del firmante"
                        value={titularCheque}
                        onChange={(e) => setTitularCheque(e.target.value)}
                      />
                    </Grid>
                    <Grid size={{ xs: 6, sm: 3 }}>
                      <TextField
                        size="small"
                        fullWidth
                        type="date"
                        label="Fecha emisión *"
                        InputLabelProps={{ shrink: true }}
                        value={fechaEmisionCheque}
                        onChange={(e) => setFechaEmisionCheque(e.target.value)}
                      />
                    </Grid>
                    <Grid size={{ xs: 6, sm: 3 }}>
                      <TextField
                        size="small"
                        fullWidth
                        type="date"
                        label="Fecha cobro / venc. *"
                        InputLabelProps={{ shrink: true }}
                        value={fechaVencCheque}
                        onChange={(e) => setFechaVencCheque(e.target.value)}
                        helperText={
                          fechaVencCheque && new Date(fechaVencCheque) > new Date()
                            ? "Diferido"
                            : "En cartera"
                        }
                      />
                    </Grid>
                  </>
                )}
              </Grid>
            </Paper>
          )}

          {(modo === "SIN_SALDO" || (modo === "REINTEGRO" && tipoReintegro === "DIFERIDO")) && (
            <Paper variant="outlined" sx={{ p: 2, bgcolor: "action.hover", borderRadius: 1.5 }}>
              <Grid container spacing={2}>
                <Grid size={{ xs: 12, sm: 6 }}>
                  <TextField
                    size="small"
                    fullWidth
                    type="date"
                    label="Fecha del cierre *"
                    InputLabelProps={{ shrink: true }}
                    value={fechaCierre}
                    onChange={(e) => setFechaCierre(e.target.value)}
                  />
                </Grid>
              </Grid>
            </Paper>
          )}

          <TextField
            size="small"
            fullWidth
            multiline
            minRows={2}
            label="Observaciones del cierre (opcional)"
            value={observaciones}
            onChange={(e) => setObservaciones(e.target.value)}
            sx={{ mt: 2 }}
          />

          <Alert severity="info" sx={{ mt: 2 }} icon={<Icon icon="mdi:lock-outline" />}>
            Una vez cerrada, la rendición es <strong>inmutable</strong>. Para modificarla habrá
            que anularla completa.
          </Alert>
        </DialogContent>
        <DialogActions>
          <Button onClick={onClose} disabled={mut.isPending}>
            Cancelar
          </Button>
          <Button
            type="submit"
            variant="contained"
            color="success"
            disabled={mut.isPending}
            startIcon={<Icon icon="mdi:check" />}
          >
            {mut.isPending ? "Cerrando..." : "Cerrar rendición"}
          </Button>
        </DialogActions>
      </form>
      {confirmDialogs}
    </Dialog>
  );
}

export default CerrarRendicionDialog;
