<template>
  <div
    v-if="modelValue"
    class="modal fade show d-block orden-detalle-modal-root"
    style="background: rgba(0, 0, 0, 0.5)"
    tabindex="-1"
    role="dialog"
    aria-modal="true"
  >
    <div class="modal-dialog modal-dialog-centered modal-lg">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">Orden {{ ordenDetalle?.folio_unico || "..." }}</h5>
          <button type="button" class="btn-close" aria-label="Cerrar" @click="cerrar"></button>
        </div>
        <div class="modal-body">
          <div v-if="detalleLoading" class="text-center py-4 text-muted">Cargando detalle...</div>
          <div v-else-if="!ordenDetalle" class="alert alert-warning mb-0">No se pudo cargar el detalle de la orden.</div>
          <div v-else>
            <div class="row g-3">
              <div class="col-md-6">
                <p class="mb-1"><strong>Cliente:</strong> {{ ordenDetalle.cliente_nombre || "-" }}</p>
                <p class="mb-1"><strong>Correo:</strong> {{ ordenDetalle.cliente_email || "-" }}</p>
                <p class="mb-1"><strong>Servicio:</strong> {{ ordenDetalle.tipo_servicio || "-" }}</p>
                <p class="mb-1"><strong>Total:</strong> ${{ Number(ordenDetalle.total || 0).toFixed(2) }}</p>
                <p class="mb-1"><strong>Subtotal:</strong> ${{ Number(ordenDetalle.subtotal || 0).toFixed(2) }}</p>
                <p class="mb-1"><strong>Impuestos:</strong> ${{ Number(ordenDetalle.impuestos || 0).toFixed(2) }}</p>
              </div>
              <div class="col-md-6">
                <p class="mb-1"><strong>Etapa:</strong> {{ etiquetaEtapa(ordenDetalle.current_step) }}</p>
                <p class="mb-1"><strong>Estatus:</strong> {{ getEstatusLabel(ordenDetalle.estatus) }}</p>
                <p class="mb-1"><strong>Recepcionista:</strong> {{ ordenDetalle.recepcionista?.name || "-" }}</p>
                <p class="mb-1"><strong>Creada:</strong> {{ formatearFecha(ordenDetalle.created_at) }}</p>
                <p class="mb-1"><strong>Pagos:</strong> {{ textoPagosOrden(ordenDetalle) }}</p>
                <p class="mb-1"><strong>Envío:</strong> {{ ordenDetalle.shipping_order?.is_delivery ? "Sí" : "No" }}</p>
              </div>
            </div>

            <hr />
            <p class="mb-1"><strong>Instrucciones:</strong> {{ ordenDetalle.instrucciones || "-" }}</p>
            <p class="mb-1"><strong>Domicilio de envío:</strong> {{ ordenDetalle.shipping_order?.delivery_address || "-" }}</p>
            <p v-if="ordenDetalle.motivo_cancelacion" class="text-danger mb-1">
              <strong>Motivo cancelación:</strong> {{ ordenDetalle.motivo_cancelacion }}
            </p>

            <hr />
            <h6 class="mb-2">Líneas de la orden</h6>
            <div v-if="!detallesCobrables.length && !detallesContenido.length" class="text-muted small">Sin líneas.</div>
            <div v-if="detallesCobrables.length" class="table-responsive">
              <table class="table table-sm mb-0">
                <thead>
                  <tr>
                    <th>Concepto</th>
                    <th class="text-end">Cant.</th>
                    <th class="text-end">P. Unit.</th>
                    <th class="text-end">Subtotal</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="d in detallesCobrables" :key="d.id">
                    <td>
                      {{ lineConceptoCobrable(d) }}
                      <span v-if="d.laundry_sale_product_id" class="badge bg-success ms-1">Catálogo POS</span>
                      <span v-else-if="d.service_type_id" class="badge bg-primary ms-1">Lavandería</span>
                      <div v-if="d.observations" class="small text-muted mt-1">{{ d.observations }}</div>
                    </td>
                    <td class="text-end">{{ formatCantidadLinea(d) }}</td>
                    <td class="text-end">${{ Number(d.precio_unitario || 0).toFixed(2) }}</td>
                    <td class="text-end">${{ Number(d.subtotal || 0).toFixed(2) }}</td>
                  </tr>
                </tbody>
              </table>
            </div>

            <div v-if="detallesContenido.length" class="mt-3">
              <h6 class="mb-1">Contenido del servicio</h6>
              <p class="small text-muted mb-2">Detalle de prendas por producto. No se cobra; aparece en el ticket.</p>
              <div class="table-responsive">
                <table class="table table-sm table-bordered mb-0 orden-contenido-table">
                  <thead class="table-light">
                    <tr>
                      <th>Detalle</th>
                      <th class="text-end" style="width: 5rem">Cant.</th>
                      <th style="width: 6rem">Cobro</th>
                    </tr>
                  </thead>
                  <tbody>
                    <template v-for="d in detallesContenido" :key="d.id">
                      <tr>
                        <td>
                          <strong>{{ lineConceptoContenido(d) }}</strong>
                        </td>
                        <td class="text-end">{{ Number(d.cantidad || 0).toFixed(0) }}</td>
                        <td class="text-muted small">Sin cargo</td>
                      </tr>
                      <tr v-if="d.observations" :key="`${d.id}-obs`">
                        <td colspan="3" class="small text-muted py-1 ps-3">→ {{ d.observations }}</td>
                      </tr>
                    </template>
                  </tbody>
                </table>
              </div>
            </div>

            <hr />
            <h6 class="mb-2">Bolsas de empaque</h6>
            <p class="small text-muted mb-2">
              Indique cuántas bolsas usa la orden. Cada bolsa obtiene un código de barras único; puede imprimir una etiqueta o todas.
            </p>
            <div v-if="!puedeModificarBolsas" class="alert alert-secondary py-2 small mb-2">
              No se pueden cambiar bolsas en órdenes entregadas o canceladas.
            </div>
            <div class="row g-2 align-items-end mb-3">
              <div class="col-auto">
                <label class="form-label mb-0">Cantidad de bolsas</label>
                <input
                  v-model.number="bolsasCantidadDraft"
                  type="number"
                  min="0"
                  max="500"
                  class="form-control"
                  style="width: 7rem"
                  :disabled="!puedeModificarBolsas || aplicandoBolsas || detalleLoading"
                />
              </div>
              <div class="col-auto">
                <button
                  type="button"
                  class="btn btn-outline-primary"
                  :disabled="!puedeModificarBolsas || aplicandoBolsas || detalleLoading || !ordenDetalle"
                  @click="aplicarCantidadBolsas"
                >
                  {{ aplicandoBolsas ? "Aplicando..." : "Aplicar" }}
                </button>
              </div>
              <div class="col-auto">
                <button
                  type="button"
                  class="btn btn-outline-secondary"
                  :disabled="
                    !puedeImprimirEtiquetasBolsas ||
                    imprimiendoBolsasPdf !== null ||
                    detalleLoading ||
                    !ordenDetalle ||
                    !bolsasList.length
                  "
                  @click="imprimirPdfBolsas(null)"
                >
                  {{ imprimiendoBolsasPdf === "all" ? "Generando..." : "Imprimir todas" }}
                </button>
              </div>
            </div>
            <div v-if="!bolsasList.length" class="text-muted small">Sin bolsas registradas. Indique cantidad y pulse Aplicar.</div>
            <div v-else class="table-responsive">
              <table class="table table-sm mb-0">
                <thead>
                  <tr>
                    <th>#</th>
                    <th>Código</th>
                    <th class="text-end">Etiqueta</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="b in bolsasList" :key="b.id">
                    <td>{{ b.indice }}</td>
                    <td>
                      <code class="small">{{ b.codigo }}</code>
                    </td>
                    <td class="text-end">
                      <button
                        type="button"
                        class="btn btn-sm btn-outline-secondary"
                        :disabled="
                          !puedeImprimirEtiquetasBolsas ||
                          imprimiendoBolsasPdf !== null ||
                          detalleLoading
                        "
                        @click="imprimirPdfBolsas(b.indice)"
                      >
                        {{
                          imprimiendoBolsasPdf === b.indice ? "Generando..." : "Imprimir"
                        }}
                      </button>
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>

            <hr />
            <div
              ref="detalleEditBlockRef"
              class="d-flex justify-content-between align-items-center mb-2 rounded p-2"
              :class="{
                'edit-block-highlight-ok': detalleResaltarEdicion && puedeEditarOrdenSeleccionada,
                'edit-block-highlight-locked': detalleResaltarEdicion && !puedeEditarOrdenSeleccionada,
              }"
            >
              <h6 class="mb-0">Editar orden</h6>
              <span v-if="!puedeEditarOrdenSeleccionada" class="badge bg-secondary">Orden cerrada o sin permiso</span>
            </div>
            <div v-if="detalleErrorEdicion" class="alert alert-danger py-2">{{ detalleErrorEdicion }}</div>
            <div class="row g-2">
              <div class="col-md-6">
                <label class="form-label">Cliente</label>
                <input
                  ref="detalleClienteInputRef"
                  v-model="detalleForm.cliente_nombre"
                  type="text"
                  class="form-control"
                  :disabled="!puedeEditarOrdenSeleccionada || guardandoDetalle"
                />
              </div>
              <div class="col-md-6">
                <label class="form-label">Correo</label>
                <input
                  v-model="detalleForm.cliente_email"
                  type="email"
                  class="form-control"
                  :disabled="!puedeEditarOrdenSeleccionada || guardandoDetalle"
                />
              </div>
              <div class="col-md-6">
                <label class="form-label">Método pago</label>
                <select
                  v-model="detalleForm.metodo_pago"
                  class="form-control"
                  :disabled="!puedeEditarOrdenSeleccionada || guardandoDetalle"
                >
                  <option value="">Sin definir</option>
                  <option value="efectivo">Efectivo</option>
                  <option value="tarjeta">Tarjeta</option>
                  <option value="transferencia">Transferencia</option>
                </select>
              </div>
              <div class="col-md-12">
                <label class="form-label">Instrucciones</label>
                <textarea
                  v-model="detalleForm.instrucciones"
                  rows="2"
                  class="form-control"
                  :disabled="!puedeEditarOrdenSeleccionada || guardandoDetalle"
                ></textarea>
              </div>
              <div class="col-md-3 d-flex align-items-center">
                <div class="form-check mt-3">
                  <input
                    id="modal-detalle-is-priority"
                    v-model="detalleForm.is_priority"
                    class="form-check-input"
                    type="checkbox"
                    :disabled="!puedeEditarOrdenSeleccionada || guardandoDetalle"
                  />
                  <label for="modal-detalle-is-priority" class="form-check-label">Prioritaria</label>
                </div>
              </div>
              <div class="col-md-3 d-flex align-items-center">
                <div class="form-check mt-3">
                  <input
                    id="modal-detalle-is-delivery"
                    v-model="detalleForm.is_delivery"
                    class="form-check-input"
                    type="checkbox"
                    :disabled="!puedeEditarOrdenSeleccionada || guardandoDetalle"
                  />
                  <label for="modal-detalle-is-delivery" class="form-check-label">Envío a domicilio</label>
                </div>
              </div>
              <div class="col-md-6">
                <label class="form-label">Domicilio de envío</label>
                <input
                  v-model="detalleForm.delivery_address"
                  type="text"
                  class="form-control"
                  :disabled="!puedeEditarOrdenSeleccionada || guardandoDetalle || !detalleForm.is_delivery"
                />
              </div>
            </div>
          </div>
        </div>
        <div class="modal-footer">
          <button
            type="button"
            class="btn btn-primary"
            :disabled="!puedeEditarOrdenSeleccionada || guardandoDetalle || detalleLoading || !ordenDetalle"
            @click="guardarDetalle"
          >
            {{ guardandoDetalle ? "Guardando..." : "Guardar cambios" }}
          </button>
          <button type="button" class="btn btn-secondary" @click="cerrar">Cerrar</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed, nextTick, onMounted, ref, watch } from "vue";
import { useOrderStepLabel } from "@/composables/use-order-step-label";
import { usePermissions } from "@/composables/use-permissions";
import * as OrdenLavanderiaRepository from "@/repositories/OrdenLavanderiaRepository";

const props = defineProps({
  modelValue: { type: Boolean, default: false },
  orderId: { type: Number, default: null },
  focusEditOnOpen: { type: Boolean, default: false },
});

const emit = defineEmits(["update:modelValue", "saved", "closed"]);

const { etiquetaEtapa } = useOrderStepLabel();
const { loadPermissions, hasPermission, userPermissions } = usePermissions();

const canEditar = computed(
  () => userPermissions.value && (hasPermission("lavanderia.recepcion") || hasPermission("pos.vender"))
);

const ordenDetalle = ref(null);
const detalleLoading = ref(false);
const guardandoDetalle = ref(false);
const detalleErrorEdicion = ref("");
const detalleEditBlockRef = ref(null);
const detalleClienteInputRef = ref(null);
const detalleResaltarEdicion = ref(false);
let detalleHighlightTimeoutId = null;

const detalleForm = ref({
  cliente_nombre: "",
  cliente_email: "",
  instrucciones: "",
  metodo_pago: "",
  is_priority: false,
  is_delivery: false,
  delivery_address: "",
});

const bolsasCantidadDraft = ref(0);
const aplicandoBolsas = ref(false);
/** @type {import('vue').Ref<null | number | 'all'>} */
const imprimiendoBolsasPdf = ref(null);

const bolsasList = computed(() => {
  const raw = ordenDetalle.value?.bolsas;
  if (!Array.isArray(raw)) return [];
  return [...raw].sort((a, b) => (Number(a.indice) || 0) - (Number(b.indice) || 0));
});

const detallesLista = computed(() => {
  const raw = ordenDetalle.value?.detalles;
  return Array.isArray(raw) ? raw : [];
});

const detallesCobrables = computed(() => detallesLista.value.filter((d) => !d.is_informational));

const detallesContenido = computed(() => detallesLista.value.filter((d) => !!d.is_informational));

function lineConceptoCobrable(d) {
  if (d.laundry_sale_product?.name) {
    const parts = [d.laundry_sale_product.name];
    if (d.service_type?.name) parts.push(d.service_type.name);
    let label = parts.join(" · ");
    if (d.load_type?.name) label += ` (${d.load_type.name})`;
    const extra = Number(d.extra_cost ?? 0);
    if (extra > 0) label += ` (+ $${extra.toFixed(2)} extra)`;
    return label;
  }
  if (d.producto?.nombre) return d.producto.nombre;
  const parts = [d.garment_type?.name, d.service_type?.name, d.load_type?.name].filter(Boolean);
  return parts.length ? parts.join(" · ") : "Línea";
}

function lineConceptoContenido(d) {
  const product = d.laundry_sale_product?.name || "—";
  const garment = d.garment_type?.name || "—";
  return `${product} → ${garment}`;
}

function formatCantidadLinea(d) {
  if ((d.billing_mode || "") === "by_weight") {
    const w = d.weight_kg != null ? Number(d.weight_kg) : Number(d.cantidad || 0);
    return `${w.toFixed(2)} kg`;
  }
  return Number(d.cantidad || 0).toFixed(2);
}

const puedeModificarBolsas = computed(() => {
  if (!canEditar.value || !ordenDetalle.value) return false;
  const e = ordenDetalle.value.estatus;
  return e !== "entregado" && e !== "cancelado";
});

const puedeImprimirEtiquetasBolsas = computed(
  () =>
    userPermissions.value &&
    (hasPermission("lavanderia.consultar") ||
      hasPermission("lavanderia.operador") ||
      hasPermission("lavanderia.recepcion") ||
      hasPermission("pos.vender"))
);

const estatusCerrados = ["terminado", "entregado", "cancelado"];
const puedeEditarOrdenSeleccionada = computed(() => {
  if (!canEditar.value || !ordenDetalle.value) return false;
  return !estatusCerrados.includes(ordenDetalle.value.estatus);
});

function getEstatusLabel(estatus) {
  const labels = {
    pendiente: "Pendiente",
    en_proceso: "En Proceso",
    terminado: "Terminado",
    entregado: "Entregado",
    cancelado: "Cancelado",
  };
  return labels[estatus] || estatus;
}

function textoPagosOrden(orden) {
  if (!orden) return "-";
  const pagos = Array.isArray(orden.pagos) ? orden.pagos : [];
  if (pagos.length) {
    return pagos.map((p) => `${p.metodo_pago} $${Number(p.monto || 0).toFixed(2)}`).join(" · ");
  }
  return orden.metodo_pago || "-";
}

function formatearFecha(fecha) {
  if (!fecha) return "-";
  return new Date(fecha).toLocaleString("es-MX", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
  });
}

function hydrateDetalleForm(orden) {
  const mp = orden?.metodo_pago || "";
  detalleForm.value = {
    cliente_nombre: orden?.cliente_nombre || "",
    cliente_email: orden?.cliente_email || "",
    instrucciones: orden?.instrucciones || "",
    metodo_pago: mp === "mixto" ? "" : mp,
    is_priority: Boolean(orden?.is_priority),
    is_delivery: Boolean(orden?.shipping_order?.is_delivery),
    delivery_address: orden?.shipping_order?.delivery_address || "",
  };
}

function syncBolsasDraftFromOrden() {
  const ord = ordenDetalle.value;
  if (!ord) {
    bolsasCantidadDraft.value = 0;
    return;
  }
  const list = Array.isArray(ord.bolsas) ? ord.bolsas : [];
  bolsasCantidadDraft.value = list.length;
}

function showMessage(msg = "", type = "success") {
  const toast = window.Swal.mixin({
    toast: true,
    position: "top-end",
    showConfirmButton: false,
    timer: 3000,
    timerProgressBar: true,
    padding: "10px 20px",
  });
  toast.fire({ icon: type, title: msg });
}

async function focusBloqueEdicion() {
  await nextTick();
  if (!puedeEditarOrdenSeleccionada.value) return;
  detalleResaltarEdicion.value = true;
  if (detalleHighlightTimeoutId) clearTimeout(detalleHighlightTimeoutId);
  detalleHighlightTimeoutId = setTimeout(() => {
    detalleResaltarEdicion.value = false;
    detalleHighlightTimeoutId = null;
  }, 2000);
  detalleEditBlockRef.value?.scrollIntoView?.({ behavior: "smooth", block: "start" });
  await nextTick();
  detalleClienteInputRef.value?.focus?.();
  detalleClienteInputRef.value?.select?.();
}

async function cargarDetalle(id) {
  detalleLoading.value = true;
  detalleErrorEdicion.value = "";
  try {
    const response = await OrdenLavanderiaRepository.getById(id);
    ordenDetalle.value = response.data || null;
    hydrateDetalleForm(ordenDetalle.value);
    syncBolsasDraftFromOrden();
  } catch (error) {
    console.error(error);
    ordenDetalle.value = null;
    showMessage("No se pudo cargar el detalle de la orden", "error");
  } finally {
    detalleLoading.value = false;
  }
}

watch(
  () => [props.modelValue, props.orderId],
  async ([show, oid]) => {
    if (!show || !oid) {
      ordenDetalle.value = null;
      detalleResaltarEdicion.value = false;
      if (detalleHighlightTimeoutId) {
        clearTimeout(detalleHighlightTimeoutId);
        detalleHighlightTimeoutId = null;
      }
      return;
    }
    await cargarDetalle(oid);
    if (ordenDetalle.value && props.focusEditOnOpen) {
      await focusBloqueEdicion();
    }
  },
  { flush: "post" }
);

function cerrar() {
  emit("update:modelValue", false);
  ordenDetalle.value = null;
  detalleErrorEdicion.value = "";
  guardandoDetalle.value = false;
  aplicandoBolsas.value = false;
  imprimiendoBolsasPdf.value = null;
  bolsasCantidadDraft.value = 0;
  detalleResaltarEdicion.value = false;
  if (detalleHighlightTimeoutId) {
    clearTimeout(detalleHighlightTimeoutId);
    detalleHighlightTimeoutId = null;
  }
  emit("closed");
}

async function guardarDetalle() {
  if (!ordenDetalle.value || !puedeEditarOrdenSeleccionada.value) return;

  guardandoDetalle.value = true;
  detalleErrorEdicion.value = "";
  try {
    const payload = {
      cliente_nombre: detalleForm.value.cliente_nombre?.trim() || "",
      cliente_email: detalleForm.value.cliente_email?.trim() || null,
      instrucciones: detalleForm.value.instrucciones?.trim() || null,
      metodo_pago: detalleForm.value.metodo_pago || null,
      is_priority: Boolean(detalleForm.value.is_priority),
      is_delivery: Boolean(detalleForm.value.is_delivery),
      delivery_address: detalleForm.value.is_delivery ? detalleForm.value.delivery_address?.trim() || null : null,
    };

    const response = await OrdenLavanderiaRepository.updateOrden(ordenDetalle.value.id, payload);
    ordenDetalle.value = response.data || ordenDetalle.value;
    hydrateDetalleForm(ordenDetalle.value);
    syncBolsasDraftFromOrden();
    showMessage("Orden actualizada correctamente", "success");
    emit("saved");
  } catch (error) {
    const msg =
      error.response?.data?.errors?.orden?.[0] ||
      error.response?.data?.errors?.cliente_nombre?.[0] ||
      error.response?.data?.message ||
      "No se pudo actualizar la orden";
    detalleErrorEdicion.value = msg;
    showMessage(msg, "error");
  } finally {
    guardandoDetalle.value = false;
  }
}

async function aplicarCantidadBolsas() {
  if (!ordenDetalle.value || !puedeModificarBolsas.value) return;
  let n = Number(bolsasCantidadDraft.value);
  if (!Number.isFinite(n) || n < 0) n = 0;
  n = Math.min(500, Math.max(0, Math.floor(n)));
  bolsasCantidadDraft.value = n;

  aplicandoBolsas.value = true;
  try {
    const response = await OrdenLavanderiaRepository.syncBolsas(ordenDetalle.value.id, n);
    ordenDetalle.value = response.data || ordenDetalle.value;
    syncBolsasDraftFromOrden();
    showMessage("Bolsas actualizadas", "success");
    emit("saved");
  } catch (error) {
    const msg =
      error.response?.data?.errors?.orden?.[0] ||
      error.response?.data?.message ||
      "No se pudo actualizar las bolsas";
    showMessage(msg, "error");
  } finally {
    aplicandoBolsas.value = false;
  }
}

async function imprimirPdfBolsas(indice) {
  if (!ordenDetalle.value?.id || !puedeImprimirEtiquetasBolsas.value) return;
  if (!bolsasList.value.length) {
    showMessage("No hay bolsas para imprimir", "warning");
    return;
  }

  imprimiendoBolsasPdf.value = indice == null ? "all" : indice;
  try {
    const res = await OrdenLavanderiaRepository.fetchBolsasPdfBlob(ordenDetalle.value.id, {
      indice: indice == null ? undefined : indice,
    });
    const ct = String(res.headers["content-type"] || "");
    if (!ct.includes("pdf")) {
      let msg = "No se pudo generar el PDF";
      try {
        const text = await res.data.text();
        const j = JSON.parse(text);
        if (j.message) msg = j.message;
      } catch {
        /* ignore */
      }
      showMessage(msg, "error");
      return;
    }
    const url = URL.createObjectURL(new Blob([res.data], { type: "application/pdf" }));
    window.open(url, "_blank");
  } catch {
    showMessage("Error al descargar el PDF de etiquetas", "error");
  } finally {
    imprimiendoBolsasPdf.value = null;
  }
}

onMounted(async () => {
  await loadPermissions();
});
</script>

<style scoped>
.edit-block-highlight-ok {
  background: #e9f9ef;
  border: 1px solid #22c55e;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

.edit-block-highlight-locked {
  background: #f3f4f6;
  border: 1px solid #9ca3af;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

.orden-detalle-modal-root {
  z-index: 1055;
}

.orden-contenido-table td {
  vertical-align: middle;
}
</style>
