<script setup>
import BaseButton from "../../../components/base/BaseButton.vue";
import BaseCheckbox from "../../../components/base/BaseCheckbox.vue";
import BaseColumn from "../../../components/base/BaseColumn.vue";
import BaseConfirmDialog from "../../../components/base/BaseConfirmDialog.vue";
import BaseDataTable from "../../../components/base/BaseDataTable.vue";
import BaseIndex from "../../../components/base/BaseIndex.vue";
import BaseInputNumber from "../../../components/base/BaseInputNumber.vue";
import BaseInputText from "../../../components/base/BaseInputText.vue";
import BaseModal from "../../../components/base/BaseModal.vue";
import BaseSelect from "../../../components/base/BaseSelect.vue";
import BaseTextarea from "../../../components/base/BaseTextarea.vue";
import { useBaseToast } from "../../../composables/useBaseToast.js";
import { useConfirm } from "primevue/useconfirm";
import { onMounted, ref, watch } from "vue";

import { useOffersApi } from "../composables/useOffersApi.js";

const toast = useBaseToast();
const confirm = useConfirm();

const {
  editorMeta,
  patchVatPresets,
  listCatalog,
  createCatalogRow,
  patchCatalogRow,
  deleteCatalogRow,
} = useOffersApi();

const loading = ref(false);
const presetsBusy = ref(false);
const presetsInput = ref("21, 9, 0");

const includeInactive = ref(true);
const rows = ref([]);
const dialogVisible = ref(false);
const saving = ref(false);
const editingId = ref(null);

const pricingOptions = [
  { label: "One-time", value: "one_time" },
  { label: "Weekly", value: "weekly" },
  { label: "Monthly", value: "monthly" },
  { label: "Hourly", value: "hourly" },
  { label: "Custom unit", value: "custom_unit" },
];

const draft = ref({
  name: "",
  default_description: "",
  default_pricing_type: "one_time",
  default_custom_unit_label: "",
  default_unit_price: 0,
  default_quantity: 1,
  default_vat_rate: 21,
  is_active: true,
});

async function hydratePresets() {
  try {
    const meta = await editorMeta();
    if (Array.isArray(meta?.vat_rate_presets)) {
      presetsInput.value = meta.vat_rate_presets.map((x) => String(x)).join(", ");
    }
  } catch {
    presetsInput.value = "21, 9, 0";
  }
}

async function savePresets() {
  presetsBusy.value = true;
  try {
    const rates = presetsInput.value
      .split(/[,;\s]+/)
      .map((s) => s.trim())
      .filter(Boolean)
      .map((x) => Number.parseFloat(x))
      .filter((n) => !Number.isNaN(n));

    await patchVatPresets(rates);
    toast.add({ severity: "success", summary: "VAT presets updated", life: 2200 });
  } catch {
    toast.add({ severity: "error", summary: "Could not save presets", life: 3200 });
  } finally {
    presetsBusy.value = false;
  }
}

async function load() {
  loading.value = true;
  try {
    const payload = await listCatalog({
      per_page: 200,
      include_inactive: includeInactive.value ? 1 : 0,
    });
    rows.value = Array.isArray(payload?.data) ? payload.data : [];
  } catch {
    rows.value = [];
    toast.add({ severity: "error", summary: "Could not load catalog", life: 3200 });
  } finally {
    loading.value = false;
  }
}

function openCreate() {
  editingId.value = null;
  draft.value = {
    name: "",
    default_description: "",
    default_pricing_type: "one_time",
    default_custom_unit_label: "",
    default_unit_price: 0,
    default_quantity: 1,
    default_vat_rate: 21,
    is_active: true,
  };
  dialogVisible.value = true;
}

function openEdit(row) {
  editingId.value = row.id;
  draft.value = {
    name: row.name ?? "",
    default_description: row.default_description ?? "",
    default_pricing_type: row.default_pricing_type ?? "one_time",
    default_custom_unit_label: row.default_custom_unit_label ?? "",
    default_unit_price: Number(row.default_unit_price ?? 0),
    default_quantity: Number(row.default_quantity ?? 1),
    default_vat_rate: Number(row.default_vat_rate ?? 21),
    is_active: !!row.is_active,
  };
  dialogVisible.value = true;
}

async function saveRow() {
  saving.value = true;
  try {
    const body = {
      name: draft.value.name.trim(),
      default_description: draft.value.default_description || null,
      default_pricing_type: draft.value.default_pricing_type,
      default_custom_unit_label: draft.value.default_custom_unit_label?.trim() || null,
      default_unit_price: draft.value.default_unit_price,
      default_quantity: draft.value.default_quantity,
      default_vat_rate: draft.value.default_vat_rate,
      is_active: draft.value.is_active,
    };

    if (!body.name) {
      toast.add({ severity: "warn", summary: "Name is required", life: 2500 });

      return;
    }

    if (editingId.value) {
      await patchCatalogRow(editingId.value, body);
    } else {
      await createCatalogRow(body);
    }
    dialogVisible.value = false;
    await load();
    toast.add({ severity: "success", summary: "Saved catalog item", life: 2200 });
  } catch {
    toast.add({ severity: "error", summary: "Save failed", life: 3400 });
  } finally {
    saving.value = false;
  }
}

function confirmRemove(row) {
  confirm.require({
    message: `Remove “${row.name}”?`,
    header: "Confirm",
    icon: "pi pi-exclamation-triangle",
    rejectProps: { label: "Cancel", severity: "secondary", outlined: true },
    acceptProps: { label: "Delete", severity: "danger" },
    accept: async () => {
      try {
        await deleteCatalogRow(row.id);
        await load();
        toast.add({ severity: "success", summary: "Deleted", life: 2000 });
      } catch {
        toast.add({ severity: "error", summary: "Delete failed", life: 3000 });
      }
    },
  });
}

async function toggleActive(row, nextActive) {
  try {
    await patchCatalogRow(row.id, { is_active: !!nextActive });
    await load();
  } catch {
    toast.add({ severity: "error", summary: "Update failed", life: 2600 });
  }
}

onMounted(async () => {
  await hydratePresets();
  await load();
});

watch(includeInactive, () => load());
</script>

<template>
  <BaseIndex title="Offer catalog" subtitle="Reuse line items inside the proposal editor picker.">
    <BaseConfirmDialog />

    <div class="rounded-xl border border-surface-200 dark:border-surface-800 bg-surface-0 dark:bg-surface-950 p-4 mb-6">
      <div class="text-sm font-semibold mb-2">Default VAT presets (editor VAT dropdown)</div>
      <div class="flex flex-wrap gap-2 items-end">
        <BaseInputText
          v-model="presetsInput"
          label="Percents — comma-separated"
          class="min-w-[16rem]"
        />
        <BaseButton
          type="button"
          variant="primary"
          label="Save presets"
          :loading="presetsBusy"
          @click="savePresets"
        />
      </div>
    </div>

    <div class="flex flex-wrap items-center gap-3 mb-3">
      <BaseButton
        type="button"
        variant="primary"
        label="New item"
        icon="plus"
        @click="openCreate"
      />
      <div class="flex items-center gap-2 text-sm ml-auto">
        <BaseCheckbox
          id="inc-inactive"
          v-model="includeInactive"
          :binary="true"
          label="Show inactive items"
        />
      </div>
    </div>

    <BaseDataTable
      :value="rows"
      :loading="loading"
      striped-rows
      responsive-layout="stack"
      breakpoint="960px"
    >
      <BaseColumn field="name" header="Name" />
      <BaseColumn field="default_pricing_type" header="Pricing type" />
      <BaseColumn header="Qty / price">
        <template #body="{ data }">{{ data.default_quantity }} × {{ data.default_unit_price }}</template>
      </BaseColumn>
      <BaseColumn field="default_vat_rate" header="VAT %" />
      <BaseColumn header="Active">
        <template #body="{ data }">
          <BaseCheckbox
            :binary="true"
            :model-value="data.is_active"
            @update:model-value="(v) => toggleActive(data, v)"
          />
        </template>
      </BaseColumn>
      <BaseColumn header="">
        <template #body="{ data }">
          <div class="flex flex-wrap gap-1 justify-end">
            <BaseButton
              variant="secondary"
              icon="pencil"
              text
              rounded
              :icon-only="true"
              aria-label="Edit"
              @click="openEdit(data)"
            />
            <BaseButton
              variant="danger"
              icon="trash"
              text
              rounded
              :icon-only="true"
              aria-label="Delete"
              @click="confirmRemove(data)"
            />
          </div>
        </template>
      </BaseColumn>
    </BaseDataTable>

    <BaseModal
      v-model:visible="dialogVisible"
      :title="editingId ? 'Edit catalog item' : 'New catalog item'"
      width="32rem"
      class="max-w-lg"
    >
      <div class="flex flex-col gap-4 text-sm">
        <BaseInputText v-model="draft.name" label="Name" fluid />
        <BaseTextarea
          v-model="draft.default_description"
          label="Default HTML description"
          :rows="5"
          placeholder="<p>...</p>"
        />
        <BaseSelect
          v-model="draft.default_pricing_type"
          label="Pricing type"
          option-label="label"
          option-value="value"
          :options="pricingOptions"
        />
        <BaseInputText
          v-if="draft.default_pricing_type === 'custom_unit'"
          v-model="draft.default_custom_unit_label"
          label="Custom unit label"
          fluid
        />
        <div class="grid grid-cols-2 gap-2">
          <BaseInputNumber v-model="draft.default_quantity" label="Qty" fluid />
          <BaseInputNumber
            v-model="draft.default_unit_price"
            label="Unit price"
            mode="decimal"
            fluid
          />
          <BaseInputNumber
            v-model="draft.default_vat_rate"
            class="col-span-2"
            label="VAT rate"
            suffix=" %"
            fluid
          />
        </div>
        <BaseCheckbox
          id="catalog-draft-active"
          v-model="draft.is_active"
          :binary="true"
          label="Active (visible to picker)"
        />
        <div class="flex justify-end gap-2 pt-3">
          <BaseButton
            type="button"
            variant="secondary"
            outlined
            label="Cancel"
            @click="dialogVisible = false"
          />
          <BaseButton
            type="button"
            variant="primary"
            label="Save"
            icon="check"
            :loading="saving"
            @click="saveRow"
          />
        </div>
      </div>
    </BaseModal>
  </BaseIndex>
</template>
