<script setup>
import BaseButton from "../../../components/base/BaseButton.vue";
import BaseIndex from "../../../components/base/BaseIndex.vue";
import B2CDataTable from "../../../components/common/B2CDataTable.vue";
import { useAuth } from "../../../composables/useAuth.js";
import { useOffersApi } from "../composables/useOffersApi.js";
import { computed, onMounted, ref } from "vue";
import { useRouter } from "vue-router";

import Button from "primevue/button";
import Dialog from "primevue/dialog";
import Message from "primevue/message";
import Select from "primevue/select";

import { useToast } from "primevue/usetoast";

const router = useRouter();
const toast = useToast();
const { permissions } = useAuth();

const { listOffers, duplicateFromTemplate, createOffer } = useOffersApi();

const canCreateOffer = computed(() => permissions.value.includes("offers.create"));

const rows = ref([]);
const totalRecords = ref(0);
const loading = ref(false);
const error = ref("");

const pagination = ref({ page: 1, limit: 15 });
const sort = ref([{ field: "updated_at", order: -1 }]);
const tableUiState = ref({
  globalSearch: "",
  filters: {},
});

const tplVisible = ref(false);
const tplMenu = ref([]);
const tplPick = ref(null);
const tplBusy = ref(false);
const creating = ref(false);

let loadTimer = null;

const columns = computed(() => [
  {
    key: "offer_number",
    header: "Number",
    type: "text",
    searchable: true,
    filterable: false,
    sortable: true,
  },
  {
    key: "subject",
    header: "Subject",
    type: "text",
    searchable: true,
    filterable: false,
    sortable: true,
  },
  {
    key: "status",
    header: "Status",
    type: "text",
    searchable: false,
    filterable: false,
    sortable: true,
  },
  {
    key: "valid_until",
    header: "Valid until",
    type: "text",
    searchable: false,
    filterable: false,
    sortable: true,
  },
]);

function criteriaSignature(globalSearch, filters) {
  return JSON.stringify({
    globalSearch: String(globalSearch ?? ""),
    filters: filters ?? {},
  });
}

/** B2CDataTable `update:state` carries search/filters only (not pagination/sort). */
function onTableState(state) {
  const nextGs = String(state?.globalSearch ?? "");
  const nextFilters =
    state?.filters && typeof state.filters === "object"
      ? { ...state.filters }
      : {};

  const prevSig = criteriaSignature(
    tableUiState.value.globalSearch,
    tableUiState.value.filters,
  );
  const nextSig = criteriaSignature(nextGs, nextFilters);

  tableUiState.value = {
    globalSearch: nextGs,
    filters: nextFilters,
  };

  if (nextSig !== prevSig) {
    pagination.value = { ...pagination.value, page: 1 };
    if (loadTimer) clearTimeout(loadTimer);
    loadTimer = setTimeout(() => {
      loadTimer = null;
      load();
    }, 380);
  }
}

function onPagination(p) {
  pagination.value = p;
  load();
}

function onSort(s) {
  sort.value = s;
  load();
}

async function load() {
  loading.value = true;
  error.value = "";
  try {
    const sort0 = sort.value?.[0];
    const sf = sort0?.field ?? "updated_at";
    const asc = Number(sort0?.order) === 1;
    const g = String(tableUiState.value?.globalSearch ?? "").trim();

    const payload = await listOffers({
      page: pagination.value.page,
      per_page: pagination.value.limit,
      search: g || undefined,
      sort_by: ["offer_number", "subject", "status", "valid_until", "updated_at"].includes(sf)
        ? sf
        : "updated_at",
      sort_dir: asc ? "asc" : "desc",
      templates_only: false,
    });

    rows.value = Array.isArray(payload?.data) ? payload.data : [];
    totalRecords.value = payload?.meta?.total ?? rows.value.length;
  } catch {
    error.value = "Could not load offers.";
  } finally {
    loading.value = false;
  }
}

onMounted(load);

async function onNew() {
  if (creating.value) return;
  creating.value = true;
  try {
    const o = await createOffer({
      subject: "Untitled offer",
      sections: [
        {
          section_role: "chapter",
          title: "General",
          description_html: "",
          rows: [],
        },
        {
          section_role: "pricing_root",
          title: "Price indication",
          description_html: "",
          children: [
            {
              section_role: "pricing_category",
              title: "General",
              description_html: "",
              rows: [
                {
                  description_html: "<p></p>",
                  pricing_type: "one_time",
                  quantity: 1,
                  unit_price: 0,
                  discount_type: "none",
                  discount_value: 0,
                  vat_rate: 21,
                  custom_unit_label: "",
                },
              ],
            },
          ],
        },
      ],
    });
    toast.add({ severity: "success", summary: "Draft created", life: 2000 });
    await router.push(`/offers/${o.id}`);
  } catch {
    toast.add({
      severity: "error",
      summary: "Could not create offer",
      life: 3500,
    });
  } finally {
    creating.value = false;
  }
}

function openRow(ev) {
  const row = ev?.data ?? ev;
  if (row?.id) {
    router.push(`/offers/${row.id}`);
  }
}

async function openTemplateDialog() {
  try {
    const res = await listOffers({ templates_only: true, per_page: 100 });
    tplMenu.value = Array.isArray(res?.data) ? res.data : [];
    tplPick.value = null;
    tplVisible.value = true;
  } catch {
    toast.add({ severity: "error", summary: "Templates unavailable", life: 3000 });
  }
}

async function startFromTemplate() {
  if (!tplPick.value) {
    toast.add({
      severity: "warn",
      summary: "Select a template first",
      life: 2500,
    });
    return;
  }
  tplBusy.value = true;
  try {
    const o = await duplicateFromTemplate({ template_id: tplPick.value.id });
    tplVisible.value = false;
    toast.add({ severity: "success", summary: "Copied from template", life: 2200 });
    await router.push(`/offers/${o.id}`);
  } catch {
    toast.add({ severity: "error", summary: "Duplicate failed", life: 3500 });
  } finally {
    tplBusy.value = false;
  }
}
</script>

<template>
  <BaseIndex title="Offers" subtitle="Quotes and customer-facing proposals.">
    <div class="mb-3 flex flex-wrap items-center gap-2">
      <BaseButton
        v-if="canCreateOffer"
        label="New draft"
        icon="pi pi-plus"
        severity="primary"
        :loading="creating"
        :disabled="creating"
        @click="onNew"
      />
      <Button
        v-if="canCreateOffer"
        label="Start from template"
        variant="text"
        icon="pi pi-copy"
        type="button"
        @click="openTemplateDialog"
      />
    </div>

    <Message v-if="error" severity="warn" class="mb-4" :closable="false">{{ error }}</Message>

    <B2CDataTable
      table-key="offers.index"
      :columns="columns"
      :rows="rows"
      :loading="loading"
      server-mode
      :total-records="totalRecords"
      :pagination="pagination"
      :sort="sort"
      :persist-to-server="true"
      search-placeholder="Zoeken…"
      :table-error="error"
      :rows-per-page-options="[10, 15, 25, 50]"
      :rows-per-page="15"
      row-clickable
      @update:pagination="onPagination"
      @update:sort="onSort"
      @update:state="onTableState($event)"
      @row-click="openRow"
    />

    <Dialog v-model:visible="tplVisible" header="Start from template" modal class="max-w-lg">
      <div class="flex flex-col gap-3">
        <Select v-model="tplPick" :options="tplMenu" option-label="template_name" placeholder="Pick template" class="w-full" />
        <Button label="Create draft" icon="pi pi-check" :loading="tplBusy" severity="primary" type="button" @click="startFromTemplate" />
      </div>
    </Dialog>
  </BaseIndex>
</template>
