<template>
  <div v-uppercase-scope class="layout-px-spacing">
    <teleport to="#breadcrumb">
      <ul class="navbar-nav flex-row">
        <li>
          <div class="page-header">
            <nav class="breadcrumb-one">
              <ol class="breadcrumb">
                <li class="breadcrumb-item"><a href="javascript:;">{{ $t("admin.laundry_pos_catalog.breadcrumb_parent") }}</a></li>
                <li class="breadcrumb-item active">{{ breadcrumbCurrent }}</li>
              </ol>
            </nav>
          </div>
        </li>
      </ul>
    </teleport>

    <div class="row layout-top-spacing">
      <div class="col-12">
        <div class="panel lavanderia-panel p-4">
          <h4 class="mb-3">{{ pageTitle }}</h4>
          <p class="text-muted small">{{ pageSubtitle }}</p>

          <ul v-if="showCatalogTabs" class="nav nav-tabs mb-3">
            <li class="nav-item">
              <button class="nav-link" :class="{ active: tab === 'categories' }" type="button" @click="setTab('categories')">
                {{ $t("admin.laundry_pos_catalog.tab_categories") }}
              </button>
            </li>
            <li class="nav-item">
              <button class="nav-link" :class="{ active: tab === 'products' }" type="button" @click="setTab('products')">
                {{ $t("admin.laundry_pos_catalog.tab_products") }}
              </button>
            </li>
          </ul>

          <div v-if="isCategoriesOnly || tab === 'categories'">
            <div class="d-flex justify-content-between mb-2">
              <button class="btn btn-outline-secondary" :disabled="loadingCat" @click="loadCategories">{{ $t("admin.laundry_pos_catalog.refresh") }}</button>
              <button class="btn btn-primary" @click="openCatCreate">{{ $t("admin.laundry_pos_catalog.new_category") }}</button>
            </div>
            <div v-if="loadingCat" class="text-center py-4"><div class="spinner-border text-primary"></div></div>
            <div v-else class="table-responsive">
              <table class="table table-bordered table-hover table-sm">
                <thead>
                  <tr>
                    <th>{{ $t("admin.laundry_pos_catalog.th_code") }}</th>
                    <th>{{ $t("admin.laundry_pos_catalog.th_name") }}</th>
                    <th>{{ $t("admin.laundry_pos_catalog.th_sort") }}</th>
                    <th>{{ $t("admin.laundry_pos_catalog.th_active") }}</th>
                    <th>{{ $t("admin.laundry_pos_catalog.th_actions") }}</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="row in categories" :key="row.id">
                    <td><code>{{ row.code }}</code></td>
                    <td>{{ row.name }}</td>
                    <td>{{ row.sort_order }}</td>
                    <td>
                      <span class="badge" :class="row.is_active ? 'bg-success' : 'bg-secondary'">{{ row.is_active ? $t("admin.laundry_pos_catalog.yes") : $t("admin.laundry_pos_catalog.no") }}</span>
                    </td>
                    <td>
                      <button class="btn btn-sm btn-outline-primary me-1" @click="openCatEdit(row)">{{ $t("admin.laundry_pos_catalog.edit") }}</button>
                      <button class="btn btn-sm btn-outline-warning me-1" :disabled="!row.is_active" @click="disableCat(row)">{{ $t("admin.laundry_pos_catalog.disable") }}</button>
                      <button class="btn btn-sm btn-outline-danger" @click="deleteCat(row)">{{ $t("common.delete_btn") }}</button>
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>

          <div v-else>
            <p v-if="isProductsCatalog" class="small mb-2">
              <router-link to="/admin/catalogo-categorias" class="text-primary">{{ $t("admin.laundry_pos_catalog.link_manage_categories") }}</router-link>
            </p>
            <div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-2">
              <button class="btn btn-outline-secondary btn-sm" :disabled="loadingProd" @click="loadProducts">{{ $t("admin.laundry_pos_catalog.refresh") }}</button>
              <button class="btn btn-primary" @click="openProdCreate">{{ newProductLabel }}</button>
            </div>

            <div class="card border mb-3">
              <div class="card-body py-3">
                <div class="row g-2 align-items-end">
                  <div class="col-md-3 col-lg-2">
                    <label class="form-label small mb-0">{{ $t("admin.laundry_pos_catalog.filter_search") }}</label>
                    <input
                      v-model="productFilters.q"
                      type="search"
                      class="form-control form-control-sm"
                      :placeholder="$t('admin.laundry_pos_catalog.filter_search_ph')"
                    />
                  </div>
                  <div class="col-md-3 col-lg-2">
                    <label class="form-label small mb-0">{{ $t("admin.laundry_pos_catalog.f_category") }}</label>
                    <select v-model="productFilters.category_id" class="form-select form-select-sm">
                      <option value="">{{ $t("admin.laundry_pos_catalog.filter_all_categories") }}</option>
                      <option v-for="c in categoriesForFilter" :key="c.id" :value="String(c.id)">{{ c.name }}</option>
                    </select>
                  </div>
                  <div class="col-md-2 col-lg-2">
                    <label class="form-label small mb-0">{{ $t("admin.laundry_pos_catalog.f_billing_unit") }}</label>
                    <select v-model="productFilters.billing_unit" class="form-select form-select-sm">
                      <option value="">{{ $t("admin.laundry_pos_catalog.filter_all") }}</option>
                      <option value="piece">{{ $t("ventas.pos.per_piece") }}</option>
                      <option value="kg">{{ $t("ventas.pos.billing_weight") }}</option>
                    </select>
                  </div>
                  <div class="col-md-2 col-lg-2">
                    <label class="form-label small mb-0">{{ $t("admin.laundry_pos_catalog.f_active") }}</label>
                    <select v-model="productFilters.is_active" class="form-select form-select-sm">
                      <option value="">{{ $t("admin.laundry_pos_catalog.filter_all") }}</option>
                      <option value="1">{{ $t("admin.laundry_pos_catalog.yes") }}</option>
                      <option value="0">{{ $t("admin.laundry_pos_catalog.no") }}</option>
                    </select>
                  </div>
                  <div class="col-md-3 col-lg-2">
                    <label class="form-label small mb-0">{{ $t("ventas.pos.etapa") }}</label>
                    <select v-model="productFilters.etapa_id" class="form-select form-select-sm">
                      <option value="">{{ $t("admin.laundry_pos_catalog.filter_all") }}</option>
                      <option v-for="st in etapas" :key="st.id" :value="String(st.id)">{{ st.name }}</option>
                    </select>
                  </div>
                  <div v-if="!lockedTipo" class="col-md-2 col-lg-2">
                    <label class="form-label small mb-0">{{ $t("admin.laundry_pos_catalog.filter_tipo") }}</label>
                    <select v-model="productFilterTipo" class="form-select form-select-sm">
                      <option value="">{{ $t("admin.laundry_pos_catalog.filter_tipo_all") }}</option>
                      <option value="servicio">{{ $t("admin.laundry_pos_catalog.tipo_servicio") }}</option>
                      <option value="producto">{{ $t("admin.laundry_pos_catalog.tipo_producto") }}</option>
                    </select>
                  </div>
                  <div class="col-md-auto">
                    <button
                      type="button"
                      class="btn btn-outline-secondary btn-sm"
                      :disabled="!hasActiveProductFilters"
                      @click="clearProductFilters"
                    >
                      {{ $t("admin.laundry_pos_catalog.filter_clear") }}
                    </button>
                  </div>
                </div>
                <p class="small text-muted mb-0 mt-2">
                  {{ $t("admin.laundry_pos_catalog.filter_results", { shown: filteredProducts.length, total: products.length }) }}
                </p>
              </div>
            </div>
            <div v-if="loadingProd" class="text-center py-4"><div class="spinner-border text-primary"></div></div>
            <div v-else class="table-responsive">
              <table class="table table-bordered table-hover table-sm">
                <thead>
                  <tr>
                    <th>{{ $t("admin.laundry_pos_catalog.th_code") }}</th>
                    <th>{{ $t("admin.laundry_pos_catalog.th_name") }}</th>
                    <th v-if="showTipoColumn">{{ $t("admin.laundry_pos_catalog.th_tipo") }}</th>
                    <th>{{ $t("admin.laundry_pos_catalog.th_category") }}</th>
                    <th>{{ $t("admin.laundry_pos_catalog.th_etapa") }}</th>
                    <th>{{ $t("admin.laundry_pos_catalog.th_billing_unit") }}</th>
                    <th class="text-end">{{ $t("admin.laundry_pos_catalog.th_unit_price") }}</th>
                    <th v-if="showStockColumn" class="text-end">{{ $t("admin.laundry_pos_catalog.th_stock") }}</th>
                    <th>{{ $t("admin.laundry_pos_catalog.th_active") }}</th>
                    <th>{{ $t("admin.laundry_pos_catalog.th_actions") }}</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="row in filteredProducts" :key="row.id">
                    <td><code>{{ row.code }}</code></td>
                    <td>{{ row.name }}</td>
                    <td v-if="showTipoColumn">
                      <span class="badge" :class="row.tipo === 'producto' ? 'bg-info' : 'bg-primary'">
                        {{ row.tipo === "producto" ? $t("admin.laundry_pos_catalog.tipo_producto") : $t("admin.laundry_pos_catalog.tipo_servicio") }}
                      </span>
                    </td>
                    <td>{{ row.category?.name || "—" }}</td>
                    <td>{{ displayCatalogLabel(row.default_etapa?.name) || "—" }}</td>
                    <td>{{ row.billing_unit === "kg" ? $t("ventas.pos.billing_weight") : $t("ventas.pos.per_piece") }}</td>
                    <td class="text-end">${{ Number(row.unit_price || 0).toFixed(2) }}</td>
                    <td v-if="showStockColumn" class="text-end">
                      <template v-if="row.tipo === 'producto' && row.billing_unit === 'piece' && row.tracks_stock">{{ row.stock_quantity ?? 0 }}</template>
                      <template v-else>—</template>
                    </td>
                    <td>
                      <span class="badge" :class="row.is_active ? 'bg-success' : 'bg-secondary'">{{ row.is_active ? $t("admin.laundry_pos_catalog.yes") : $t("admin.laundry_pos_catalog.no") }}</span>
                    </td>
                    <td>
                      <button class="btn btn-sm btn-outline-primary me-1" @click="openProdEdit(row)">{{ $t("admin.laundry_pos_catalog.edit") }}</button>
                      <button class="btn btn-sm btn-outline-warning me-1" :disabled="!row.is_active" @click="disableProd(row)">{{ $t("admin.laundry_pos_catalog.disable") }}</button>
                      <button class="btn btn-sm btn-outline-danger" @click="deleteProd(row)">{{ $t("common.delete_btn") }}</button>
                    </td>
                  </tr>
                  <tr v-if="filteredProducts.length === 0">
                    <td :colspan="productsTableColspan" class="text-center text-muted py-3">{{ $t("admin.laundry_pos_catalog.products_empty") }}</td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="modal fade" id="modalLaundryCat" tabindex="-1" ref="modalCatEl">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title">{{ editingCat ? $t("admin.laundry_pos_catalog.modal_edit_cat") : $t("admin.laundry_pos_catalog.modal_new_cat") }}</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
          </div>
          <div class="modal-body">
            <div v-if="editingCat" class="mb-2">
              <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_code") }}</label>
              <input v-model="catForm.code" class="form-control" disabled />
            </div>
            <div class="mb-2">
              <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_name") }}</label>
              <input v-model="catForm.name" class="form-control" />
              <p v-if="!editingCat" class="text-muted small mb-0 mt-1">{{ $t("common.code_auto_hint") }}</p>
            </div>
            <div class="mb-2">
              <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_sort") }}</label>
              <input v-model.number="catForm.sort_order" type="number" min="0" class="form-control" />
            </div>
            <div class="mb-2">
              <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_active") }}</label>
              <select v-model="catForm.is_active" class="form-select">
                <option :value="true">{{ $t("admin.laundry_pos_catalog.yes") }}</option>
                <option :value="false">{{ $t("admin.laundry_pos_catalog.no") }}</option>
              </select>
            </div>
          </div>
          <div class="modal-footer">
            <button class="btn btn-light" data-bs-dismiss="modal">{{ $t("admin.laundry_pos_catalog.cancel") }}</button>
            <button class="btn btn-primary" :disabled="savingCat" @click="saveCat">{{ savingCat ? $t("admin.laundry_pos_catalog.saving") : $t("admin.laundry_pos_catalog.save") }}</button>
          </div>
        </div>
      </div>
    </div>

    <div class="modal fade" id="modalLaundryProd" tabindex="-1" ref="modalProdEl">
      <div class="modal-dialog modal-xl">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title">{{ prodModalTitle }}</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
          </div>
          <div class="modal-body">
            <div class="row">
              <div :class="editingProd ? 'col-md-6 mb-2' : 'col-md-12 mb-2'">
                <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_category") }}</label>
                <select v-model.number="prodForm.laundry_sale_category_id" class="form-select">
                  <option v-for="c in categories" :key="c.id" :value="c.id">{{ c.name }}</option>
                </select>
              </div>
              <div v-if="editingProd" class="col-md-6 mb-2">
                <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_code") }}</label>
                <input v-model="prodForm.code" class="form-control" disabled />
              </div>
            </div>
            <div class="mb-2">
              <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_name") }}</label>
              <input v-model="prodForm.name" class="form-control" />
              <p v-if="!editingProd" class="text-muted small mb-0 mt-1">{{ $t("common.code_auto_hint") }}</p>
            </div>
            <div v-if="!lockedTipo" class="mb-2">
              <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_tipo") }}</label>
              <select v-model="prodForm.tipo" class="form-select">
                <option value="servicio">{{ $t("admin.laundry_pos_catalog.tipo_servicio") }}</option>
                <option value="producto">{{ $t("admin.laundry_pos_catalog.tipo_producto") }}</option>
              </select>
            </div>
            <div class="mb-2">
              <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_description") }}</label>
              <textarea v-model="prodForm.description" class="form-control" rows="2"></textarea>
            </div>
            <div class="row">
              <div class="col-md-4 mb-2">
                <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_billing_unit") }}</label>
                <select v-model="prodForm.billing_unit" class="form-select">
                  <option value="piece">{{ $t("ventas.pos.per_piece") }}</option>
                  <option value="kg">{{ $t("ventas.pos.billing_weight") }}</option>
                </select>
              </div>
              <div class="col-md-4 mb-2">
                <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_unit_price") }}</label>
                <input v-model="prodForm.unit_price" type="number" min="0" step="0.01" class="form-control" />
                <div class="form-text">{{ $t("admin.laundry_pos_catalog.unit_price_help") }}</div>
              </div>
              <div class="col-md-4 mb-2">
                <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_sort") }}</label>
                <input v-model.number="prodForm.sort_order" type="number" min="0" class="form-control" />
              </div>
            </div>
            <div class="row">
              <div class="col-md-6 mb-2">
                <label class="form-label">{{ $t("ventas.pos.etapa") }}</label>
                <select v-model="prodForm.default_etapa_id" class="form-select">
                  <option :value="null">{{ $t("ventas.pos.optional") }}</option>
                  <option v-for="st in etapas" :key="st.id" :value="st.id">{{ displayCatalogLabel(st.name) }}</option>
                </select>
              </div>
              <div class="col-md-6 mb-2">
                <label class="form-label">{{ $t("ventas.pos.load_type") }}</label>
                <select v-model="prodForm.default_load_type_id" class="form-select">
                  <option :value="null">{{ $t("ventas.pos.optional") }}</option>
                  <option v-for="lt in loadTypes" :key="lt.id" :value="lt.id">{{ displayCatalogLabel(lt.name) }}</option>
                </select>
              </div>
            </div>
            <div class="mb-2">
              <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_active") }}</label>
              <select v-model="prodForm.is_active" class="form-select">
                <option :value="true">{{ $t("admin.laundry_pos_catalog.yes") }}</option>
                <option :value="false">{{ $t("admin.laundry_pos_catalog.no") }}</option>
              </select>
            </div>
            <div v-if="showStockForm" class="row align-items-end">
              <div class="col-md-6 mb-2">
                <div class="form-check mt-2">
                  <input
                    id="chkTracksStock"
                    v-model="prodForm.tracks_stock"
                    class="form-check-input"
                    type="checkbox"
                    :disabled="prodForm.billing_unit !== 'piece'"
                  />
                  <label class="form-check-label" for="chkTracksStock">{{ $t("admin.laundry_pos_catalog.f_tracks_stock") }}</label>
                </div>
                <div class="form-text">{{ $t("admin.laundry_pos_catalog.tracks_stock_help") }}</div>
              </div>
              <div class="col-md-6 mb-2">
                <label class="form-label">{{ $t("admin.laundry_pos_catalog.f_stock_quantity") }}</label>
                <input
                  v-model="prodForm.stock_quantity"
                  type="number"
                  min="0"
                  step="1"
                  class="form-control"
                  :disabled="!prodForm.tracks_stock || prodForm.billing_unit !== 'piece'"
                />
              </div>
            </div>

          </div>
          <div class="modal-footer">
            <button class="btn btn-light" data-bs-dismiss="modal">{{ $t("admin.laundry_pos_catalog.cancel") }}</button>
            <button class="btn btn-primary" :disabled="savingProd" @click="saveProd">{{ savingProd ? $t("admin.laundry_pos_catalog.saving") : $t("admin.laundry_pos_catalog.save") }}</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed, onMounted, ref, watch } from "vue";
import { useI18n } from "vue-i18n";
import { useRoute, useRouter } from "vue-router";
import { useConfirmDelete } from "@/composables/useConfirmDelete";
import * as Repo from "@/repositories/LaundryPosCatalogAdminRepository";
import { displayCatalogLabel } from "@/utils/displayCatalogLabel";

const { t } = useI18n();
const { confirmDelete } = useConfirmDelete();
const route = useRoute();
const router = useRouter();

/** @param {unknown} q */
function tabFromQuery(q) {
  const t = typeof q === "string" ? q : "";
  return t === "products" || t === "categories" ? t : "categories";
}

const lockedTipo = computed(() => {
  const t = route.meta?.lockedTipo;
  return t === "producto" || t === "servicio" ? t : "";
});
const isCategoriesOnly = computed(() => route.meta?.catalogMode === "categories");
const isProductsCatalog = computed(() => !!lockedTipo.value);
const showCatalogTabs = computed(() => !isCategoriesOnly.value && !isProductsCatalog.value);
const showStockColumn = computed(() => lockedTipo.value === "producto");
const showTipoColumn = computed(() => !lockedTipo.value);
const showStockForm = computed(() => (lockedTipo.value || prodForm.value.tipo) === "producto");

const pageTitle = computed(() => {
  if (isCategoriesOnly.value) return t("admin.laundry_pos_catalog.title_categories");
  if (lockedTipo.value === "producto") return t("admin.laundry_pos_catalog.title_producto");
  if (lockedTipo.value === "servicio") return t("admin.laundry_pos_catalog.title_servicio");
  return t("admin.laundry_pos_catalog.title");
});
const pageSubtitle = computed(() => {
  if (isCategoriesOnly.value) return t("admin.laundry_pos_catalog.subtitle_categories");
  if (lockedTipo.value === "producto") return t("admin.laundry_pos_catalog.subtitle_producto");
  if (lockedTipo.value === "servicio") return t("admin.laundry_pos_catalog.subtitle_servicio");
  return t("admin.laundry_pos_catalog.subtitle");
});
const breadcrumbCurrent = computed(() => {
  if (isCategoriesOnly.value) return t("admin.laundry_pos_catalog.breadcrumb_categories");
  if (lockedTipo.value === "producto") return t("admin.laundry_pos_catalog.breadcrumb_producto");
  if (lockedTipo.value === "servicio") return t("admin.laundry_pos_catalog.breadcrumb_servicio");
  return t("admin.laundry_pos_catalog.breadcrumb_current");
});
const newProductLabel = computed(() => {
  if (lockedTipo.value === "producto") return t("admin.laundry_pos_catalog.new_producto");
  if (lockedTipo.value === "servicio") return t("admin.laundry_pos_catalog.new_servicio");
  return t("admin.laundry_pos_catalog.new_product");
});
const prodModalTitle = computed(() => {
  const editing = editingProd.value;
  if (lockedTipo.value === "producto") {
    return editing
      ? t("admin.laundry_pos_catalog.modal_edit_prod_producto")
      : t("admin.laundry_pos_catalog.modal_new_prod_producto");
  }
  if (lockedTipo.value === "servicio") {
    return editing
      ? t("admin.laundry_pos_catalog.modal_edit_prod_servicio")
      : t("admin.laundry_pos_catalog.modal_new_prod_servicio");
  }
  return editing ? t("admin.laundry_pos_catalog.modal_edit_prod") : t("admin.laundry_pos_catalog.modal_new_prod");
});
const productsTableColspan = computed(() => 8 + (showTipoColumn.value ? 1 : 0) + (showStockColumn.value ? 1 : 0));

const tab = ref("categories");

function syncTabFromRoute() {
  if (isCategoriesOnly.value) {
    tab.value = "categories";
  } else if (isProductsCatalog.value) {
    tab.value = "products";
  } else {
    tab.value = tabFromQuery(route.query.tab);
  }
}

watch(
  () => [route.path, route.meta.catalogMode, route.meta.lockedTipo, route.query.tab],
  () => {
    syncTabFromRoute();
    if (lockedTipo.value) {
      productFilterTipo.value = lockedTipo.value;
    }
  },
  { immediate: true },
);

/** @param {'categories' | 'products'} name */
function setTab(name) {
  tab.value = name;
  router.replace({ path: route.path, query: { ...route.query, tab: name } });
}

const loadingCat = ref(true);
const loadingProd = ref(false);
const savingCat = ref(false);
const savingProd = ref(false);
const categories = ref([]);
const products = ref([]);
const productFilterTipo = ref("");
const defaultProductFilters = () => ({
  q: "",
  category_id: "",
  billing_unit: "",
  is_active: "",
  etapa_id: "",
});
const productFilters = ref(defaultProductFilters());

const categoriesForFilter = computed(() => {
  const list = categories.value || [];
  return [...list].sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0) || String(a.name || "").localeCompare(String(b.name || "")));
});

const filteredProducts = computed(() => {
  let list = products.value || [];
  const f = productFilters.value;
  const tipo = lockedTipo.value || productFilterTipo.value;
  if (tipo) {
    list = list.filter((p) => (p.tipo || "servicio") === tipo);
  }
  const q = (f.q || "").trim().toLowerCase();
  if (q) {
    list = list.filter((p) => {
      const haystack = [p.name, p.code, p.description].filter(Boolean).join(" ").toLowerCase();
      return haystack.includes(q);
    });
  }
  if (f.category_id) {
    list = list.filter((p) => Number(p.laundry_sale_category_id) === Number(f.category_id));
  }
  if (f.billing_unit) {
    list = list.filter((p) => p.billing_unit === f.billing_unit);
  }
  if (f.is_active === "1") {
    list = list.filter((p) => !!p.is_active);
  } else if (f.is_active === "0") {
    list = list.filter((p) => !p.is_active);
  }
  if (f.etapa_id) {
    list = list.filter((p) => Number(p.default_etapa_id) === Number(f.etapa_id));
  }
  return list;
});

const hasActiveProductFilters = computed(() => {
  const f = productFilters.value;
  return !!(
    (f.q || "").trim()
    || f.category_id
    || f.billing_unit
    || f.is_active
    || f.etapa_id
    || (!lockedTipo.value && productFilterTipo.value)
  );
});

function clearProductFilters() {
  productFilters.value = defaultProductFilters();
  if (!lockedTipo.value) {
    productFilterTipo.value = "";
  }
}
const loadTypes = ref([]);
const etapas = ref([]);
const editingCat = ref(false);
const editingProd = ref(false);
const catEditId = ref(null);
const prodEditId = ref(null);
const modalCatEl = ref(null);
const modalProdEl = ref(null);
let modalCat = null;
let modalProd = null;

const catForm = ref({ code: "", name: "", sort_order: 0, is_active: true });
const prodForm = ref({
  laundry_sale_category_id: null,
  code: "",
  name: "",
  tipo: "servicio",
  description: "",
  billing_unit: "piece",
  unit_price: "",
  sort_order: 0,
  default_etapa_id: null,
  default_load_type_id: null,
  is_active: true,
  tracks_stock: false,
  stock_quantity: "",
});

watch(
  () => prodForm.value.billing_unit,
  (u) => {
    if (u !== "piece") {
      prodForm.value.tracks_stock = false;
    }
  },
);

watch(
  () => [prodForm.value.tipo, lockedTipo.value],
  () => {
    const effectiveTipo = lockedTipo.value || prodForm.value.tipo;
    if (effectiveTipo === "servicio") {
      prodForm.value.tracks_stock = false;
      prodForm.value.stock_quantity = "";
    }
  },
);

function firstApiErrorMessage(err) {
  const d = err?.response?.data;
  if (!d) return null;
  if (d.message && typeof d.message === "string") return d.message;
  const errs = d.errors;
  if (errs && typeof errs === "object") {
    const first = Object.values(errs).flat()[0];
    if (typeof first === "string") return first;
  }
  return null;
}

function toast(msg, icon) {
  window.Swal?.mixin({ toast: true, position: "top-end", showConfirmButton: false, timer: 3500 })?.fire({ icon, title: msg });
}

/** @param {boolean} editing */
function savedProdMessageKey(editing) {
  if (lockedTipo.value === "producto") {
    return editing ? "admin.laundry_pos_catalog.saved_prod_producto" : "admin.laundry_pos_catalog.created_prod_producto";
  }
  if (lockedTipo.value === "servicio") {
    return editing ? "admin.laundry_pos_catalog.saved_prod_servicio" : "admin.laundry_pos_catalog.created_prod_servicio";
  }
  return editing ? "admin.laundry_pos_catalog.saved_prod" : "admin.laundry_pos_catalog.created_prod";
}

function disabledProdMessageKey() {
  if (lockedTipo.value === "producto") return "admin.laundry_pos_catalog.disabled_prod_producto";
  if (lockedTipo.value === "servicio") return "admin.laundry_pos_catalog.disabled_prod_servicio";
  return "admin.laundry_pos_catalog.disabled_prod";
}

async function loadCategories() {
  loadingCat.value = true;
  try {
    const body = await Repo.listCategories();
    categories.value = Array.isArray(body?.data) ? body.data : [];
  } catch {
    categories.value = [];
    toast(t("admin.laundry_pos_catalog.load_error"), "error");
  } finally {
    loadingCat.value = false;
  }
}

async function loadProducts() {
  loadingProd.value = true;
  try {
    const body = await Repo.listProducts(lockedTipo.value || undefined);
    products.value = Array.isArray(body?.data) ? body.data : [];
    loadTypes.value = body?.meta?.load_types || [];
    etapas.value = body?.meta?.etapas || [];
    const mc = body?.meta?.laundry_sale_categories;
    if (Array.isArray(mc) && mc.length) categories.value = mc;
  } catch {
    products.value = [];
    toast(t("admin.laundry_pos_catalog.load_error"), "error");
  } finally {
    loadingProd.value = false;
  }
}

function openCatCreate() {
  editingCat.value = false;
  catEditId.value = null;
  catForm.value = { code: "", name: "", sort_order: 0, is_active: true };
  modalCat?.show();
}

function openCatEdit(row) {
  editingCat.value = true;
  catEditId.value = row.id;
  catForm.value = {
    code: row.code,
    name: row.name,
    sort_order: row.sort_order ?? 0,
    is_active: !!row.is_active,
  };
  modalCat?.show();
}

async function saveCat() {
  savingCat.value = true;
  try {
    if (editingCat.value && catEditId.value) {
      await Repo.updateCategory(catEditId.value, {
        name: catForm.value.name,
        sort_order: catForm.value.sort_order,
        is_active: catForm.value.is_active,
      });
      toast(t("admin.laundry_pos_catalog.saved_cat"), "success");
    } else {
      await Repo.createCategory({
        name: catForm.value.name,
        sort_order: catForm.value.sort_order,
        is_active: catForm.value.is_active,
      });
      toast(t("admin.laundry_pos_catalog.created_cat"), "success");
    }
    modalCat?.hide();
    await loadCategories();
  } catch {
    toast(t("admin.laundry_pos_catalog.save_error"), "error");
  } finally {
    savingCat.value = false;
  }
}

async function disableCat(row) {
  try {
    await Repo.disableCategory(row.id);
    toast(t("admin.laundry_pos_catalog.disabled_cat"), "success");
    await loadCategories();
  } catch {
    toast(t("admin.laundry_pos_catalog.save_error"), "error");
  }
}

async function deleteCat(row) {
  await confirmDelete({
    label: row.name,
    onDelete: () => Repo.deleteCategory(row.id),
    onSuccess: async () => {
      toast(t("common.deleted_ok"), "success");
      await loadCategories();
    },
  });
}

function openProdCreate() {
  editingProd.value = false;
  prodEditId.value = null;
  prodForm.value = {
    laundry_sale_category_id: categories.value[0]?.id ?? null,
    code: "",
    name: "",
    tipo: lockedTipo.value || "servicio",
    description: "",
    billing_unit: "piece",
    unit_price: "",
    sort_order: 0,
    default_etapa_id: null,
    default_load_type_id: null,
    is_active: true,
    tracks_stock: false,
    stock_quantity: "",
  };
  modalProd?.show();
}

function openProdEdit(row) {
  editingProd.value = true;
  prodEditId.value = row.id;
  prodForm.value = {
    laundry_sale_category_id: row.laundry_sale_category_id,
    code: row.code,
    name: row.name,
    tipo: row.tipo || "servicio",
    description: row.description || "",
    billing_unit: row.billing_unit || "piece",
    unit_price: row.unit_price != null ? String(row.unit_price) : "",
    sort_order: row.sort_order ?? 0,
    default_etapa_id: row.default_etapa_id ?? null,
    default_load_type_id: row.default_load_type_id ?? null,
    is_active: !!row.is_active,
    tracks_stock: !!(row.tracks_stock && row.billing_unit === "piece"),
    stock_quantity: row.stock_quantity != null && row.stock_quantity !== "" ? String(row.stock_quantity) : "",
  };
  modalProd?.show();
}

async function saveProd() {
  const effectiveTipo = lockedTipo.value || prodForm.value.tipo || "servicio";
  const tracks =
    effectiveTipo === "producto" && prodForm.value.billing_unit === "piece" && !!prodForm.value.tracks_stock;
  if (tracks) {
    const q = prodForm.value.stock_quantity === "" || prodForm.value.stock_quantity === null
      ? NaN
      : Number(prodForm.value.stock_quantity);
    if (!Number.isFinite(q) || q < 0) {
      toast(t("admin.laundry_pos_catalog.stock_need_qty"), "error");
      return;
    }
  }
  savingProd.value = true;
  try {
    const stockQty = tracks
      ? Math.max(0, Math.round(Number(prodForm.value.stock_quantity)))
      : null;
    const payload = {
      laundry_sale_category_id: Number(prodForm.value.laundry_sale_category_id),
      name: prodForm.value.name,
      tipo: effectiveTipo,
      description: prodForm.value.description || null,
      billing_unit: prodForm.value.billing_unit,
      unit_price: Number(prodForm.value.unit_price),
      sort_order: prodForm.value.sort_order ?? 0,
      is_active: prodForm.value.is_active,
      default_etapa_id: prodForm.value.default_etapa_id ?? null,
      default_load_type_id: prodForm.value.default_load_type_id ?? null,
      tracks_stock: tracks,
      stock_quantity: stockQty,
      service_prices: [],
    };
    if (editingProd.value && prodEditId.value) {
      payload.code = prodForm.value.code;
    }
    if (editingProd.value && prodEditId.value) {
      await Repo.updateProduct(prodEditId.value, payload);
      toast(t(savedProdMessageKey(true)), "success");
    } else {
      await Repo.createProduct(payload);
      toast(t(savedProdMessageKey(false)), "success");
    }
    modalProd?.hide();
    await loadProducts();
  } catch (e) {
    toast(firstApiErrorMessage(e) || t("admin.laundry_pos_catalog.save_error"), "error");
  } finally {
    savingProd.value = false;
  }
}

async function disableProd(row) {
  try {
    await Repo.disableProduct(row.id);
    toast(t(disabledProdMessageKey()), "success");
    await loadProducts();
  } catch {
    toast(t("admin.laundry_pos_catalog.save_error"), "error");
  }
}

async function deleteProd(row) {
  await confirmDelete({
    label: row.name,
    onDelete: () => Repo.deleteProduct(row.id),
    onSuccess: async () => {
      toast(t("common.deleted_ok"), "success");
      await loadProducts();
    },
  });
}

onMounted(async () => {
  const bs = window.bootstrap;
  if (bs && modalCatEl.value) modalCat = new bs.Modal(modalCatEl.value);
  if (bs && modalProdEl.value) modalProd = new bs.Modal(modalProdEl.value);
  if (isCategoriesOnly.value) {
    await loadCategories();
  } else {
    await loadCategories();
    await loadProducts();
  }
});

watch(
  () => route.path,
  async () => {
    if (isProductsCatalog.value || tab.value === "products") {
      await loadProducts();
    }
  },
);
</script>
