import { Icon } from "@iconify/react";
import {
  Alert,
  Autocomplete,
  Box,
  Button,
  Chip,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  Divider,
  FormControlLabel,
  Grid,
  IconButton,
  MenuItem,
  Paper,
  Stack,
  Switch,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  TextField,
  Typography,
} from "@mui/material";
import { useQuery } from "@tanstack/react-query";
import { useEffect, useMemo, useState } from "react";
import { getTiposGasto } from "../../../api/gastos.service";
import { searchProveedores } from "../../../api/proveedores.service";
import { useDebouncedValue } from "../../../hooks/useDebouncedValue";
import { MonedaInput } from "../../common/MonedaInput";
import { fmtMoneda } from "../../_standards/enums/monedas";
import { useAgregarGastoRendicionMutation } from "../../../tanstack/RendicionViaticosStack";
import { hoyISO } from "../../../utils/fecha";

const TODAY = () => hoyISO();

const emptyItem = () => ({
  tipo_gasto_id: "",
  descripcion: "",
  cantidad: 1,
  precio_unitario: 0,
  porcentaje_iva: 10,
});

/**
 * Diálogo para agregar un gasto vinculado a una rendición.
 * Modo con factura: proveedor + timbrado + IVA crédito.
 * Modo sin factura: solo tipo + descripción + monto.
 * Ver docs/plan-rendicion-viaticos.md — Fase 2.
 */
export function AgregarGastoRendicionDialog({ open, onClose, rendicion }) {
  const [conFactura, setConFactura] = useState(true);
  const [proveedor, setProveedor] = useState(null);
  const [proveedorInput, setProveedorInput] = useState("");
  const [ruc, setRuc] = useState("");
  const [timbrado, setTimbrado] = useState("");
  const [establecimiento, setEstablecimiento] = useState("");
  const [puntoExpedicion, setPuntoExpedicion] = useState("");
  const [numeroFactura, setNumeroFactura] = useState("");
  // Los comprobantes de una rendición se cargan a mano, así que casi siempre son
  // de talonario. Se destilda solo si el proveedor emitió factura electrónica.
  const [esPreimpreso, setEsPreimpreso] = useState(true);
  const [fechaEmision, setFechaEmision] = useState(TODAY());
  const [descripcion, setDescripcion] = useState("");
  const [items, setItems] = useState([emptyItem()]);
  const [errors, setErrors] = useState([]);

  const mut = useAgregarGastoRendicionMutation();
  const monedaCodigo = rendicion?.moneda?.codigo || "PYG";

  const { data: tiposGastoResp } = useQuery({
    queryKey: ["tipos-gasto-viaticos"],
    queryFn: getTiposGasto,
    enabled: open,
    staleTime: 5 * 60 * 1000,
  });
  const tiposGasto = Array.isArray(tiposGastoResp)
    ? tiposGastoResp
    : tiposGastoResp?.data ?? tiposGastoResp?.items ?? [];

  const proveedorSearch = useDebouncedValue(proveedorInput, 400);
  const { data: proveedoresResp, isFetching: proveedoresLoading } = useQuery({
    queryKey: ["proveedores-viaticos", proveedorSearch],
    queryFn: () => searchProveedores(proveedorSearch, 10),
    enabled: open && conFactura && proveedorSearch.trim().length >= 2,
    staleTime: 30 * 1000,
    keepPreviousData: true,
  });
  const proveedores = Array.isArray(proveedoresResp) ? proveedoresResp : [];

  useEffect(() => {
    if (open) {
      setConFactura(true);
      setProveedor(null);
      setProveedorInput("");
      setRuc("");
      setTimbrado("");
      setEstablecimiento("");
      setPuntoExpedicion("");
      setNumeroFactura("");
      setEsPreimpreso(true);
      setFechaEmision(TODAY());
      setDescripcion("");
      setItems([emptyItem()]);
      setErrors([]);
    }
  }, [open]);

  // Auto-completar RUC del proveedor si lo elige.
  useEffect(() => {
    if (proveedor?.personas?.ruc) {
      const dv = proveedor.personas.dv ? `-${proveedor.personas.dv}` : "";
      setRuc(`${proveedor.personas.ruc}${dv}`);
    }
  }, [proveedor]);

  const total = useMemo(
    () =>
      items.reduce(
        (a, it) => a + (Number(it.cantidad) || 0) * (Number(it.precio_unitario) || 0),
        0,
      ),
    [items],
  );

  const totalIvaEstimado = useMemo(() => {
    if (!conFactura) return 0;
    return items.reduce((a, it) => {
      const sub = (Number(it.cantidad) || 0) * (Number(it.precio_unitario) || 0);
      const pct = Number(it.porcentaje_iva) || 0;
      if (pct === 0) return a;
      const base = sub / (1 + pct / 100);
      return a + (sub - base);
    }, 0);
  }, [items, conFactura]);

  const setItem = (idx, field, value) => {
    setItems((arr) => arr.map((it, i) => (i === idx ? { ...it, [field]: value } : it)));
  };
  const addItem = () => setItems((arr) => [...arr, emptyItem()]);
  const removeItem = (idx) =>
    setItems((arr) => (arr.length <= 1 ? arr : arr.filter((_, i) => i !== idx)));

  const validate = () => {
    const errs = [];
    if (!fechaEmision) errs.push("Cargá la fecha del gasto.");
    if (items.length === 0) errs.push("Agregá al menos un ítem.");
    items.forEach((it, i) => {
      if (!it.tipo_gasto_id) errs.push(`Ítem ${i + 1}: elegí el tipo de gasto.`);
      if (Number(it.cantidad) <= 0) errs.push(`Ítem ${i + 1}: cantidad debe ser > 0.`);
      if (Number(it.precio_unitario) <= 0) errs.push(`Ítem ${i + 1}: precio debe ser > 0.`);
    });
    if (conFactura) {
      if (!timbrado || !/^\d{8}$/.test(timbrado)) errs.push("Timbrado debe tener 8 dígitos.");
      if (!establecimiento) errs.push("Establecimiento es obligatorio.");
      if (!puntoExpedicion) errs.push("Punto de expedición es obligatorio.");
      if (!numeroFactura) errs.push("Número de factura es obligatorio.");
      if (!ruc.trim()) errs.push("RUC del proveedor es obligatorio.");
    }
    setErrors(errs);
    return errs.length === 0;
  };

  const handleSubmit = async () => {
    if (!validate()) return;
    const dto = {
      con_factura: conFactura,
      fecha_emision: fechaEmision,
      descripcion: descripcion || undefined,
      items: items.map((it) => ({
        tipo_gasto_id: it.tipo_gasto_id,
        descripcion: it.descripcion || undefined,
        cantidad: Number(it.cantidad),
        precio_unitario: Number(it.precio_unitario),
        porcentaje_iva: conFactura ? Number(it.porcentaje_iva) : 0,
      })),
    };
    if (conFactura) {
      Object.assign(dto, {
        proveedor_id: proveedor?.id,
        ruc: ruc,
        timbrado: timbrado,
        establecimiento: establecimiento,
        punto_expedicion: puntoExpedicion,
        numero_factura: numeroFactura,
        es_preimpreso: esPreimpreso,
      });
    }
    try {
      await mut.mutateAsync({ id: rendicion.id, dto });
      onClose?.();
    } catch {
      /* la mutación muestra el toast */
    }
  };

  return (
    <Dialog open={open} onClose={mut.isPending ? undefined : onClose} maxWidth="lg" fullWidth>
      <form onSubmit={(e) => { e.preventDefault(); handleSubmit(); }}>
        <DialogTitle sx={{ display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }}>
          <Icon icon="mdi:receipt-text-plus" />
          Agregar gasto a la rendición
          <Chip
            size="small"
            variant="outlined"
            color={conFactura ? "success" : "warning"}
            icon={<Icon icon={conFactura ? "mdi:receipt-text-check" : "mdi:receipt-text-remove"} />}
            label={conFactura ? "Con factura legal (deducible)" : "Sin factura (no deducible)"}
            sx={{ ml: 1 }}
          />
          <FormControlLabel
            sx={{ ml: "auto" }}
            control={
              <Switch
                checked={conFactura}
                onChange={(e) => setConFactura(e.target.checked)}
              />
            }
            label={
              <Typography variant="body2">
                {conFactura ? "Con factura" : "Sin factura"}
              </Typography>
            }
          />
        </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>
          )}

          {!conFactura && (
            <Alert severity="warning" sx={{ mb: 2 }} icon={<Icon icon="mdi:alert-outline" />}>
              Este gasto se registrará como <strong>no deducible</strong> — no genera IVA crédito
              ni aparece en el Libro IVA Compras. Cargá solo descripción + monto por ítem.
            </Alert>
          )}

          {/* Datos generales */}
          <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:file-document-outline" width={18} />
              <Typography variant="caption" fontWeight={700} sx={{ letterSpacing: 0.5, color: "text.secondary" }}>
                DATOS GENERALES
              </Typography>
            </Box>
            <Grid container spacing={2}>
              <Grid size={{ xs: 6, md: 3 }}>
                <TextField
                  size="small"
                  fullWidth
                  type="date"
                  label="Fecha del gasto *"
                  InputLabelProps={{ shrink: true }}
                  value={fechaEmision}
                  onChange={(e) => setFechaEmision(e.target.value)}
                />
              </Grid>
              <Grid size={{ xs: 12, md: 9 }}>
                <TextField
                  size="small"
                  fullWidth
                  label="Descripción / observaciones (opcional)"
                  placeholder="Ej: cena de negocio con cliente ACME"
                  value={descripcion}
                  onChange={(e) => setDescripcion(e.target.value)}
                />
              </Grid>
            </Grid>
          </Paper>

          {/* Documento fiscal — solo si con factura */}
          {conFactura && (
            <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:receipt-text" width={18} />
                <Typography variant="caption" fontWeight={700} sx={{ letterSpacing: 0.5, color: "text.secondary" }}>
                  DOCUMENTO DEL PROVEEDOR
                </Typography>
              </Box>
              <Grid container spacing={2}>
                <Grid size={{ xs: 12, md: 6 }}>
                  <Autocomplete
                    size="small"
                    options={proveedores}
                    value={proveedor}
                    inputValue={proveedorInput}
                    onInputChange={(_, v) => setProveedorInput(v)}
                    onChange={(_, v) => setProveedor(v)}
                    filterOptions={(x) => x}
                    loading={proveedoresLoading}
                    loadingText="Buscando…"
                    noOptionsText={
                      proveedorSearch.trim().length < 2
                        ? "Escribí al menos 2 caracteres"
                        : "Sin coincidencias"
                    }
                    getOptionLabel={(o) => o?.personas?.razon_social || o?.personas?.ruc || ""}
                    isOptionEqualToValue={(o, v) => o?.id === v?.id}
                    renderInput={(params) => (
                      <TextField {...params} label="Proveedor" placeholder="Buscar por RUC o razón social…" />
                    )}
                    renderOption={(props, o) => (
                      <Box component="li" {...props} key={o.id}>
                        <Box>
                          <Typography variant="body2" fontWeight={600}>
                            {o.personas?.razon_social}
                          </Typography>
                          <Typography variant="caption" color="text.secondary">
                            {o.personas?.ruc ? `RUC ${o.personas.ruc}-${o.personas.dv || 0}` : "Sin RUC"}
                          </Typography>
                        </Box>
                      </Box>
                    )}
                  />
                </Grid>
                <Grid size={{ xs: 12, md: 3 }}>
                  <TextField
                    size="small"
                    fullWidth
                    label="RUC *"
                    placeholder="Ej: 80050001-7"
                    value={ruc}
                    onChange={(e) => setRuc(e.target.value)}
                  />
                </Grid>
                <Grid size={{ xs: 12, md: 3 }}>
                  <TextField
                    size="small"
                    fullWidth
                    label="Timbrado *"
                    placeholder="8 dígitos"
                    inputProps={{ inputMode: "numeric", maxLength: 8 }}
                    value={timbrado}
                    onChange={(e) => setTimbrado(e.target.value.replace(/\D/g, ""))}
                  />
                </Grid>
                <Grid size={{ xs: 4, md: 2 }}>
                  <TextField
                    size="small"
                    fullWidth
                    label="Est. *"
                    placeholder="001"
                    inputProps={{ inputMode: "numeric", maxLength: 3 }}
                    value={establecimiento}
                    onChange={(e) => setEstablecimiento(e.target.value.replace(/\D/g, ""))}
                  />
                </Grid>
                <Grid size={{ xs: 4, md: 2 }}>
                  <TextField
                    size="small"
                    fullWidth
                    label="P.Exp. *"
                    placeholder="001"
                    inputProps={{ inputMode: "numeric", maxLength: 3 }}
                    value={puntoExpedicion}
                    onChange={(e) => setPuntoExpedicion(e.target.value.replace(/\D/g, ""))}
                  />
                </Grid>
                <Grid size={{ xs: 4, md: 3 }}>
                  <TextField
                    size="small"
                    fullWidth
                    label="Nº factura *"
                    placeholder="0000123"
                    value={numeroFactura}
                    onChange={(e) => setNumeroFactura(e.target.value)}
                  />
                </Grid>
                <Grid size={12}>
                  <FormControlLabel
                    control={
                      <Switch
                        checked={esPreimpreso}
                        onChange={(e) => setEsPreimpreso(e.target.checked)}
                      />
                    }
                    label={
                      <Box>
                        <Typography variant="body2">Comprobante preimpreso</Typography>
                        <Typography variant="caption" color="text.secondary">
                          Destildalo si es una factura electrónica: la DNIT ya la tiene y no se
                          vuelve a declarar en el Libro IVA Compras.
                        </Typography>
                      </Box>
                    }
                  />
                </Grid>
              </Grid>
            </Paper>
          )}

          {/* Ítems */}
          <Paper variant="outlined" sx={{ p: 2, bgcolor: "action.hover", borderRadius: 1.5 }}>
            <Box sx={{ display: "flex", alignItems: "center", gap: 1, mb: 1.5, flexWrap: "wrap" }}>
              <Icon icon="mdi:format-list-bulleted" width={18} />
              <Typography variant="caption" fontWeight={700} sx={{ letterSpacing: 0.5, color: "text.secondary" }}>
                ÍTEMS
              </Typography>
              <Button
                sx={{ ml: "auto" }}
                size="small"
                variant="outlined"
                startIcon={<Icon icon="mdi:plus" />}
                onClick={addItem}
              >
                Agregar ítem
              </Button>
            </Box>

            <TableContainer>
              <Table size="small">
                <TableHead>
                  <TableRow>
                    <TableCell sx={{ fontWeight: 600, minWidth: 200 }}>Tipo de gasto</TableCell>
                    <TableCell sx={{ fontWeight: 600, minWidth: 200 }}>Descripción</TableCell>
                    <TableCell sx={{ fontWeight: 600, minWidth: 90 }} align="right">Cantidad</TableCell>
                    <TableCell sx={{ fontWeight: 600, minWidth: 120 }} align="right">Precio unit.</TableCell>
                    {conFactura && (
                      <TableCell sx={{ fontWeight: 600, minWidth: 80 }} align="center">IVA %</TableCell>
                    )}
                    <TableCell sx={{ fontWeight: 600, minWidth: 120 }} align="right">Subtotal</TableCell>
                    <TableCell align="center" />
                  </TableRow>
                </TableHead>
                <TableBody>
                  {items.map((it, idx) => {
                    const sub = (Number(it.cantidad) || 0) * (Number(it.precio_unitario) || 0);
                    return (
                      <TableRow key={idx}>
                        <TableCell>
                          <Autocomplete
                            size="small"
                            options={tiposGasto}
                            value={tiposGasto.find((t) => t.id === it.tipo_gasto_id) || null}
                            onChange={(_, v) => {
                              setItems((arr) =>
                                arr.map((row, i) =>
                                  i === idx
                                    ? {
                                        ...row,
                                        tipo_gasto_id: v?.id ?? "",
                                        // Autocompletar descripción con el nombre del tipo
                                        // si el operador no la escribió aún.
                                        descripcion:
                                          !row.descripcion?.trim() && v?.descripcion
                                            ? v.descripcion
                                            : row.descripcion,
                                      }
                                    : row,
                                ),
                              );
                            }}
                            getOptionLabel={(o) => o?.descripcion || ""}
                            isOptionEqualToValue={(o, v) => o?.id === v?.id}
                            renderInput={(params) => (
                              <TextField {...params} placeholder="Buscar tipo…" />
                            )}
                          />
                        </TableCell>
                        <TableCell>
                          <TextField
                            size="small"
                            fullWidth
                            value={it.descripcion}
                            onChange={(e) => setItem(idx, "descripcion", e.target.value)}
                            placeholder="Detalle (opcional)"
                            inputProps={{ tabIndex: -1 }}
                          />
                        </TableCell>
                        <TableCell>
                          <TextField
                            size="small"
                            type="number"
                            value={it.cantidad}
                            onChange={(e) => setItem(idx, "cantidad", e.target.value)}
                            inputProps={{ min: 0, step: "0.0001", style: { textAlign: "right" } }}
                          />
                        </TableCell>
                        <TableCell>
                          <MonedaInput
                            value={it.precio_unitario}
                            onChange={(v) => setItem(idx, "precio_unitario", v)}
                            moneda={monedaCodigo}
                            size="small"
                            fullWidth
                          />
                        </TableCell>
                        {conFactura && (
                          <TableCell align="center">
                            <TextField
                              select
                              size="small"
                              value={it.porcentaje_iva ?? 10}
                              onChange={(e) => setItem(idx, "porcentaje_iva", Number(e.target.value))}
                              sx={{ minWidth: 70 }}
                            >
                              <MenuItem value={0}>0%</MenuItem>
                              <MenuItem value={5}>5%</MenuItem>
                              <MenuItem value={10}>10%</MenuItem>
                            </TextField>
                          </TableCell>
                        )}
                        <TableCell align="right">
                          <Typography fontWeight={700}>
                            {fmtMoneda(sub, monedaCodigo)}
                          </Typography>
                        </TableCell>
                        <TableCell align="center">
                          <IconButton
                            size="small"
                            color="error"
                            onClick={() => removeItem(idx)}
                            disabled={items.length <= 1}
                          >
                            <Icon icon="mdi:delete-outline" width={18} />
                          </IconButton>
                        </TableCell>
                      </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
            </TableContainer>

            <Divider sx={{ my: 2 }} />

            <Stack direction="row" spacing={4} justifyContent="flex-end">
              {conFactura && totalIvaEstimado > 0 && (
                <Box>
                  <Typography variant="caption" color="text.secondary">
                    IVA estimado
                  </Typography>
                  <Typography variant="body1" fontWeight={600}>
                    {fmtMoneda(totalIvaEstimado, monedaCodigo)}
                  </Typography>
                </Box>
              )}
              <Box>
                <Typography variant="caption" color="text.secondary">
                  Total del gasto
                </Typography>
                <Typography variant="h6" fontWeight={700} color="success.main">
                  {fmtMoneda(total, monedaCodigo)}
                </Typography>
              </Box>
            </Stack>
          </Paper>
        </DialogContent>
        <DialogActions>
          <Button onClick={onClose} disabled={mut.isPending}>
            Cancelar
          </Button>
          <Button
            type="submit"
            variant="contained"
            disabled={mut.isPending}
            startIcon={<Icon icon="mdi:content-save-outline" />}
          >
            {mut.isPending ? "Guardando..." : "Guardar gasto"}
          </Button>
        </DialogActions>
      </form>
    </Dialog>
  );
}

export default AgregarGastoRendicionDialog;
