<template>
  <div class="layout-px-spacing">
    <teleport to="#breadcrumb">
      <ul class="navbar-nav flex-row">
        <li>
          <div class="page-header">
            <nav class="breadcrumb-one" aria-label="breadcrumb">
              <ol class="breadcrumb">
                <li class="breadcrumb-item">
                  <a href="javascript:;">{{ $t("lavanderia.escanear.breadcrumb_parent") }}</a>
                </li>
                <li class="breadcrumb-item active" aria-current="page">
                  <span>{{ $t("lavanderia.escanear.breadcrumb_current") }}</span>
                </li>
              </ol>
            </nav>
          </div>
        </li>
      </ul>
    </teleport>

    <div class="row layout-top-spacing">
      <div class="col-xl-12 col-lg-12 col-sm-12 layout-spacing">
        <div class="panel p-3">
          <div class="row">
            <div class="col-xl-12 col-lg-12 col-sm-12">
              <div class="text-center titulo-dorado">
                <h3 class="pull-left">{{ $t("lavanderia.escanear.heading") }}</h3>
              </div>
            </div>
          </div>

          <div class="row mt-4">
            <div class="col-md-5">
              <div class="card">
                <div class="card-body">
                  <div
                    class="alert mb-3"
                    :class="operatorBlocked ? 'alert-warning' : 'alert-info'"
                    role="status"
                  >
                    <strong>{{ operatorBlocked ? $t("lavanderia.escanear.operator_blocked_title") : $t("lavanderia.escanear.operator_area_title") }}</strong>
                    <div class="small mt-1">
                      <template v-if="operatorBlocked">
                        {{ $t("lavanderia.escanear.operator_blocked_body") }}
                      </template>
                      <template v-else>
                        {{ $t("lavanderia.escanear.operator_area_body", { area: areaLabel }) }}
                      </template>
                    </div>
                  </div>

                  <div v-if="operableAreas.length > 1" class="form-group mb-3">
                    <label>{{ $t("lavanderia.escanear.operator_area_select_label") }}</label>
                    <select v-model="areaCode" class="form-select" @change="onAreaChanged">
                      <option v-for="code in operableAreas" :key="code" :value="code">
                        {{ $t(`lavanderia.area.codes.${code}`) }}
                      </option>
                    </select>
                  </div>

                  <div class="form-group mb-3">
                    <label>{{ $t("lavanderia.escanear.operator_select_label") }} *</label>
                    <select
                      v-model.number="selectedOperatorId"
                      class="form-select"
                      :disabled="operatorsLoading || !operators.length"
                    >
                      <option :value="null" disabled>{{ $t("lavanderia.escanear.operator_select_placeholder") }}</option>
                      <option v-for="op in operators" :key="op.id" :value="op.id">
                        {{ op.name }}{{ op.area?.name ? ` — ${op.area.name}` : "" }}
                      </option>
                    </select>
                    <p v-if="operatorsLoading" class="small text-muted mt-1 mb-0">
                      {{ $t("lavanderia.escanear.operator_select_loading") }}
                    </p>
                    <p v-else-if="!operators.length && areaCode" class="small text-warning mt-1 mb-0">
                      {{ $t("lavanderia.escanear.operator_select_empty") }}
                    </p>
                  </div>

                  <div class="form-group mb-3">
                    <label>{{ $t("lavanderia.escanear.scan_label") }}</label>
                    <input
                      ref="scanInputRef"
                      type="text"
                      class="form-control form-control-lg text-center"
                      :placeholder="$t('lavanderia.escanear.scan_placeholder')"
                      v-model="scanValue"
                      :disabled="operatorBlocked"
                      @keyup.enter="onScan"
                      autofocus
                    />
                    <p class="small text-muted mt-2 mb-0">
                      {{ $t("lavanderia.escanear.scan_hint") }}
                    </p>
                  </div>

                  <button
                    type="button"
                    class="btn btn-primary btn-lg w-100"
                    @click="onScan"
                    :disabled="operatorBlocked || !scanValue || scanRunning || !selectedOperatorId"
                  >
                    {{
                      scanRunning
                        ? $t("lavanderia.escanear.scan_btn_loading")
                        : $t("lavanderia.escanear.scan_btn")
                    }}
                  </button>

                  <div v-if="scanError" class="alert alert-danger mt-3" role="alert">
                    {{ scanError }}
                  </div>

                  <div
                    v-if="validationErrors && Object.keys(validationErrors).length"
                    class="alert alert-warning mt-3"
                    role="alert"
                  >
                    <ul class="mb-0 ps-3">
                      <li v-for="(msgs, key) in validationErrors" :key="key">
                        <span v-for="(m, i) in msgs" :key="i">{{ m }}</span>
                      </li>
                    </ul>
                  </div>

                  <div v-if="scanSuccess" class="card mt-3">
                    <div class="card-body">
                      <h5 class="card-title text-success mb-2">
                        ✓ {{ $t("lavanderia.escanear.scan_registered") }}
                      </h5>

                      <p class="mb-1 small">
                        <strong>{{ $t("lavanderia.escanear.scan_sequence_label") }}:</strong>
                        <span class="badge ms-1" :class="scanSequenceBadgeClass">
                          {{ scanSequenceText }}
                        </span>
                      </p>

                      <p class="mb-1 small">
                        <strong>{{ $t("lavanderia.escanear.presence_status_label") }}:</strong>
                        <span class="badge bg-info ms-1">
                          {{ presenceStatusText }}
                        </span>
                      </p>

                      <p v-if="lastScanFolio" class="mb-0 small">
                        <strong>{{ $t("lavanderia.escanear.found_line_short") }}:</strong>
                        <span class="ms-1">{{ lastScanFolio }}</span>
                      </p>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <div class="col-md-7 mt-3 mt-md-0">
              <div class="card">
                <div class="card-body">
                  <div class="d-flex justify-content-between align-items-center mb-3">
                    <h5 class="mb-0">{{ $t("lavanderia.escanear.ticket_title") }}</h5>
                    <button
                      v-if="ticket && ticketOrderId"
                      type="button"
                      class="btn btn-outline-primary btn-sm"
                      @click="refreshTicket"
                      :disabled="ticketLoading"
                    >
                      {{ ticketLoading ? $t("lavanderia.escanear.refresh_loading") : $t("lavanderia.escanear.refresh_btn") }}
                    </button>
                  </div>

                  <div v-if="ticketLoading" class="text-center py-4">
                    <div class="spinner-border text-primary" role="status"></div>
                    <div class="small text-muted mt-2">
                      {{ $t("lavanderia.escanear.ticket_loading") }}
                    </div>
                  </div>

                  <div v-else-if="!ticket" class="alert alert-info mb-0">
                    {{ $t("lavanderia.escanear.order_no_ticket") }}
                  </div>

                  <div v-else>
                    <div
                      v-if="ticketSessionHighlight"
                      class="alert alert-light border border-success mb-3 py-2 px-3"
                      role="status"
                    >
                      <div class="small fw-semibold text-success mb-1">
                        {{ $t("lavanderia.escanear.ticket_last_scan_title") }}
                      </div>
                      <div class="fw-bold">{{ ticketSessionHighlight.areaLine }}</div>
                      <div class="small text-muted">{{ ticketSessionHighlight.sequenceLine }}</div>
                    </div>

                    <p class="mb-2">
                      <strong>{{ $t("lavanderia.escanear.ticket_folio_label") }}:</strong>
                      {{ ticket.folio_unico || "—" }}
                    </p>
                    <p class="mb-2">
                      <strong>{{ $t("lavanderia.escanear.ticket_estatus_label") }}:</strong>
                      <span class="badge bg-secondary ms-1">
                        {{ orderEstatusText }}
                      </span>
                    </p>
                    <p v-if="ticket.current_step" class="mb-1">
                      <strong>{{ $t("lavanderia.escanear.ticket_current_step_label") }}:</strong>
                      <span class="badge bg-info ms-1">
                        {{ etiquetaEtapa(ticket.current_step) }}
                      </span>
                    </p>
                    <p class="small text-muted mb-3">
                      {{ $t("lavanderia.escanear.ticket_global_step_hint") }}
                    </p>

                    <div v-if="ticket.presences && ticket.presences.length" class="mb-3">
                      <div class="mb-2">
                        <strong>{{ $t("lavanderia.escanear.presences_title") }}</strong>
                      </div>
                      <ul class="list-unstyled mb-0">
                        <li
                          v-for="p in ticket.presences"
                          :key="p.id"
                          class="mb-2 small"
                        >
                          <span class="text-muted">{{ areaDisplayLine(p.area) }}</span>:
                          <span class="ms-1 badge" :class="presenceBadgeClass(p.status)">
                            {{ presenceStatusTextBy(p.status) }}
                          </span>
                        </li>
                      </ul>
                    </div>

                    <div v-if="ticket.recent_scans && ticket.recent_scans.length" class="mb-1">
                      <div class="mb-2">
                        <strong>{{ $t("lavanderia.escanear.recent_scans_title") }}</strong>
                      </div>
                      <ul class="list-unstyled small mb-0">
                        <li
                          v-for="(s, idx) in ticket.recent_scans"
                          :key="idx"
                          class="mb-1"
                        >
                          <span class="text-muted">{{ areaLabelFromCode(s.area_code) }}</span>
                          · {{ scanSequenceTextBy(s.scan_sequence) }}
                          <span v-if="s.scanned_at" class="text-muted ms-1">({{ formatTime(s.scanned_at) }})</span>
                        </li>
                      </ul>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <loading v-model:active="scanLoading" :can-cancel="false" :is-full-page="true" />
  </div>
</template>

<script setup>
import { computed, nextTick, onMounted, ref, watch } from "vue";
import Loading from "vue-loading-overlay";
import "vue-loading-overlay/dist/css/index.css";
import { useI18n } from "vue-i18n";
import { useMeta } from "@/composables/use-meta";
import { useOrderStepLabel } from "@/composables/use-order-step-label";
import { useAreaLabel } from "@/composables/useAreaLabel";
import { usePermissions } from "@/composables/use-permissions";
import store from "@/store";
import { TIBU_AREA_CODES } from "@/constants/tibuAreas";
import * as UserRepository from "@/repositories/UserRepository";
import * as OrderPresenceRepository from "@/repositories/OrderPresenceRepository";
import { useLaundryScan } from "@/composables/useLaundryScan";
import { useScanOperators } from "@/composables/useScanOperators";
import { normalizeLaundryScanInput } from "@/utils/laundryScanInput";

const { t, locale } = useI18n();
const { etiquetaEtapa } = useOrderStepLabel();
const { areaLabelFromCode, areaDisplayLine } = useAreaLabel();

useMeta({ title: t("lavanderia.escanear.page_title") });

const scanInputRef = ref(null);
const scanValue = ref("");

const currentUser = ref(null);
const areaCode = ref("");
const selectedOperatorId = ref(null);

const { operators, loading: operatorsLoading, load: loadOperators } = useScanOperators(areaCode);

const ticketLoading = ref(false);
const ticket = ref(null);
const ticketOrderId = ref(null);

const scanInputFocus = async () => {
  await nextTick();
  scanInputRef.value?.focus?.();
  scanInputRef.value?.select?.();
};

const showMessage = (msg = "", type = "success") => {
  const toast = window.Swal.mixin({
    toast: true,
    position: "top",
    showConfirmButton: false,
    timer: 2500,
    timerProgressBar: true,
  });
  toast.fire({ icon: type, title: msg });
};

const { loadPermissions, hasPermission } = usePermissions();
const operableAreas = computed(() =>
  TIBU_AREA_CODES.filter((code) => hasPermission(`area.${code}.operate`))
);

const operatorBlocked = computed(() => !areaCode.value || !selectedOperatorId.value);

const areaLabel = computed(() => areaLabelFromCode(areaCode.value));

const {
  loading: scanLoading,
  error: scanError,
  validationErrors,
  lastData,
  submitScan,
  reset,
} = useLaundryScan();

const scanRunning = computed(() => Boolean(scanLoading.value));

const scanSuccess = computed(() => Boolean(lastData.value?.presence?.status));

const lastScanFolio = computed(() => lastData.value?.orden?.folio_unico || "");

const scanSequenceText = computed(() => {
  const seq = lastData.value?.scan_sequence;
  if (seq === 1) return t("lavanderia.escanear.scan_sequence_entry");
  if (seq === 2) return t("lavanderia.escanear.scan_sequence_exit");
  return String(seq ?? "");
});

const scanSequenceBadgeClass = computed(() => {
  const seq = lastData.value?.scan_sequence;
  if (seq === 1) return "bg-info";
  if (seq === 2) return "bg-success";
  return "bg-secondary";
});

const presenceStatusText = computed(() => {
  const status = lastData.value?.presence?.status;
  return presenceStatusTextBy(status);
});

function presenceStatusTextBy(status) {
  if (!status) return "—";
  const key = `lavanderia.escanear.presence_status_${String(status)}`;
  const translated = t(key);
  return translated === key ? String(status) : translated;
}

function presenceBadgeClass(status) {
  if (!status) return "badge bg-secondary";
  if (status === "pending") return "badge bg-warning";
  if (status === "in_progress") return "badge bg-info";
  if (status === "completed") return "badge bg-success";
  return "badge bg-secondary";
}

function scanSequenceTextBy(seq) {
  if (seq === 2) return t("lavanderia.escanear.scan_sequence_exit");
  return t("lavanderia.escanear.scan_sequence_entry");
}

function formatTime(iso) {
  if (!iso) return "";
  try {
    return new Date(iso).toLocaleString("es-MX");
  } catch {
    return iso;
  }
}

const orderEstatusText = computed(() => {
  const est = ticket.value?.estatus;
  if (!est) return "—";
  const key = `lavanderia.escanear.order_status_${String(est)}`;
  const translated = t(key);
  return translated === key ? String(est) : translated;
});

/** Resalta área + entrada/salida (sesión o último evento en servidor). */
const ticketSessionHighlight = computed(() => {
  const ld = lastData.value;
  if (ld?.area?.code && ld.scan_sequence != null) {
    return {
      areaLine: areaLabelFromCode(ld.area.code),
      sequenceLine: scanSequenceText.value,
    };
  }
  const rs = ticket.value?.recent_scans?.[0];
  if (rs?.area_code) {
    const name = areaLabelFromCode(rs.area_code);
    const seq =
      Number(rs.scan_sequence) === 2
        ? t("lavanderia.escanear.scan_sequence_exit")
        : t("lavanderia.escanear.scan_sequence_entry");
    return { areaLine: name, sequenceLine: seq };
  }
  return null;
});

async function loadTicket(orderId) {
  if (!orderId) return;
  ticketLoading.value = true;
  try {
    const res = await OrderPresenceRepository.getLaundryStateByOrderId(orderId);
    ticket.value = res?.data ?? res ?? null;
    ticketOrderId.value = orderId;
  } catch (e) {
    console.error(e);
    ticket.value = null;
  } finally {
    ticketLoading.value = false;
  }
}

const refreshTicket = async () => {
  if (!ticketOrderId.value) return;
  await loadTicket(ticketOrderId.value);
};

const resolveAreaCode = () => {
  const assigned = currentUser.value?.area?.code;
  if (assigned) {
    areaCode.value = String(assigned).trim();
    return;
  }
  areaCode.value = operableAreas.value[0] ?? "";
};

function pickDefaultOperator() {
  const uid = currentUser.value?.id;
  const list = operators.value;
  if (!list.length) {
    selectedOperatorId.value = null;
    return;
  }
  if (uid && list.some((o) => o.id === uid)) {
    selectedOperatorId.value = uid;
    return;
  }
  selectedOperatorId.value = list[0].id;
}

async function onAreaChanged() {
  await loadOperators();
  pickDefaultOperator();
}

watch(operators, () => pickDefaultOperator());

async function onScan() {
  if (!selectedOperatorId.value) {
    showMessage(t("lavanderia.escanear.operator_blocked_body_short"), "warning");
    return;
  }
  if (!areaCode.value) {
    showMessage(t("lavanderia.escanear.operator_area_missing"), "warning");
    return;
  }
  const raw = normalizeLaundryScanInput(scanValue.value);
  if (!raw) return;
  scanValue.value = raw;

  reset(); // limpia errores/validaciones previas, pero mantenemos `lastData` del escaneo exitoso
  try {
    const res = await submitScan({
      qrOrFolio: raw,
      areaCode: areaCode.value,
      operatorUserId: selectedOperatorId.value,
    });

    const orderId =
      res?.data?.orden?.id ?? res?.data?.orden_id ?? lastData.value?.orden?.id ?? lastData.value?.orden_id ?? null;
    if (orderId) {
      await loadTicket(orderId);
    }

    scanValue.value = "";
    showMessage(t("lavanderia.escanear.scan_registered_toast"), "success");
    await scanInputFocus();
  } catch (_) {
    // `useLaundryScan` ya deja los errores en refs para mostrar en la UI
    await scanInputFocus();
  }
}

onMounted(async () => {
  if (locale.value !== "es") {
    store.commit("toggleLocale", "es");
  }

  await loadPermissions();

  try {
    currentUser.value = await UserRepository.getuser();
  } catch (e) {
    console.error(e);
    currentUser.value = null;
  }

  resolveAreaCode();
  await loadOperators();
  pickDefaultOperator();
  await scanInputFocus();
});
</script>

<style scoped>
.card {
  transition: all 0.3s ease;
}
</style>

