<script setup>
import BaseIndex from "../../../components/base/BaseIndex.vue";
import Button from "primevue/button";
import Checkbox from "primevue/checkbox";
import Column from "primevue/column";
import ConfirmDialog from "primevue/confirmdialog";
import DataTable from "primevue/datatable";
import Dialog from "primevue/dialog";
import Dropdown from "primevue/dropdown";
import InputNumber from "primevue/inputnumber";
import InputText from "primevue/inputtext";
import Textarea from "primevue/textarea";

import { useToast } from "primevue/usetoast";
import { useConfirm } from "primevue/useconfirm";
import { onMounted, ref, watch } from "vue";

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

const toast = useToast();
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.">
    <ConfirmDialog />

    <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">
        <label class="flex flex-col gap-1 text-xs font-medium opacity-85">
          Percents — comma-separated
          <InputText v-model="presetsInput" class="min-w-[16rem]" />
        </label>
        <Button type="button" label="Save presets" :loading="presetsBusy" @click="savePresets" />
      </div>
    </div>

    <div class="flex flex-wrap items-center gap-3 mb-3">
      <Button type="button" label="New item" icon="pi pi-plus" @click="openCreate" />
      <div class="flex items-center gap-2 text-sm ml-auto">
        <Checkbox v-model="includeInactive" binary input-id="inc-inactive" />
        <label for="inc-inactive">Show inactive items</label>
      </div>
    </div>

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

    <Dialog v-model:visible="dialogVisible" modal :header="editingId ? 'Edit catalog item' : 'New catalog item'" class="max-w-lg">
      <div class="flex flex-col gap-3 text-sm">
        <label class="flex flex-col gap-1">
          <span>Name</span>
          <InputText v-model="draft.name" />
        </label>
        <label class="flex flex-col gap-1">
          <span>Default HTML description</span>
          <Textarea v-model="draft.default_description" rows="5" placeholder="<p>...</p>" />
        </label>
        <label class="flex flex-col gap-1">
          <span>Pricing type</span>
          <Dropdown v-model="draft.default_pricing_type" option-label="label" option-value="value" :options="pricingOptions" />
        </label>
        <label v-if="draft.default_pricing_type === 'custom_unit'" class="flex flex-col gap-1">
          <span>Custom unit label</span>
          <InputText v-model="draft.default_custom_unit_label" />
        </label>
        <div class="grid grid-cols-2 gap-2">
          <label class="flex flex-col gap-1">
            <span>Qty</span>
            <InputNumber v-model="draft.default_quantity" fluid />
          </label>
          <label class="flex flex-col gap-1">
            <span>Unit price</span>
            <InputNumber v-model="draft.default_unit_price" mode="decimal" fluid />
          </label>
          <label class="flex flex-col gap-1 col-span-2">
            <span>VAT rate</span>
            <InputNumber v-model="draft.default_vat_rate" suffix=" %" fluid />
          </label>
        </div>
        <div class="flex items-center gap-2">
          <Checkbox v-model="draft.is_active" binary input-id="catalog-draft-active" />
          <label class="cursor-pointer select-none text-sm" for="catalog-draft-active">
            Active (visible to picker)
          </label>
        </div>
        <div class="flex justify-end gap-2 pt-3">
          <Button type="button" outlined label="Cancel" @click="dialogVisible = false" />
          <Button type="button" label="Save" severity="primary" :loading="saving" icon="pi pi-check" @click="saveRow" />
        </div>
      </div>
    </Dialog>
  </BaseIndex>
</template>
