<script setup>
import BaseButton from "../../../components/base/BaseButton.vue";
import BaseIndex from "../../../components/base/BaseIndex.vue";
import B2CDataTable from "../../../components/common/B2CDataTable.vue";

import BaseConfirmDialog from "../../../components/base/BaseConfirmDialog.vue";

import CustomerForm from "./partials/CustomerForm.vue";
import {
  useCustomerForm,
  useCustomerList,
} from "../composables/useCustomers.js";
import { mergeDataTableColumns } from "../../../composables/mergeDataTableColumns.js";
import { ACTIVE_INACTIVE_BADGES } from "../../../constants/badgeStyles.js";
import { getDataTableColumns } from "../../../services/dataTableService.js";
import { ensureCsrf } from "../../../services/api.js";
import { useConfirm } from "primevue/useconfirm";
import { nextTick, onMounted, computed, ref } from "vue";
import { useRouter } from "vue-router";

const router = useRouter();
const confirm = useConfirm();

const {
  rows,
  totalRecords,
  totalAllRecords,
  loading,
  error,
  pagination,
  sort,
  load,
  onTableState,
} = useCustomerList();

const RESOURCE_KEY = "customers";

/** When the API is unavailable (e.g. module off), keep list usable. */
const staticColumnFallback = [
  {
    key: "name",
    header: "Name",
    type: "text",
    searchable: true,
    filterable: true,
    sortable: true,
    defaultVisible: true,
  },
  {
    key: "email",
    header: "Email",
    type: "text",
    searchable: true,
    filterable: true,
    sortable: true,
    defaultVisible: true,
  },
  {
    key: "phone",
    header: "Phone",
    type: "text",
    searchable: true,
    filterable: true,
    sortable: true,
    defaultVisible: true,
  },
  {
    key: "is_active",
    header: "Active",
    type: "badge",
    filterType: "boolean",
    searchable: false,
    filterable: true,
    sortable: true,
    defaultVisible: true,
  },
  {
    key: "id",
    header: "ID",
    type: "number",
    searchable: false,
    filterable: false,
    sortable: false,
    defaultVisible: false,
  },
  {
    key: "created_at",
    header: "Created at",
    type: "date",
    searchable: false,
    filterable: true,
    sortable: true,
    defaultVisible: false,
  },
];

/** @type {import('vue').Ref<Array<Record<string, unknown>>>} */
const apiColumnsRaw = ref([]);

const columns = computed(() => {
  const source =
    apiColumnsRaw.value.length > 0 ? apiColumnsRaw.value : staticColumnFallback;
  return mergeDataTableColumns(source, {
    is_active: {
      type: "badge",
      filterType: "boolean",
      valueMap: ACTIVE_INACTIVE_BADGES,
      defaultBadgeEntry: ACTIVE_INACTIVE_BADGES.false,
    },
  });
});

const { saving, errors, create, update, remove } = useCustomerForm();

const dialogVisible = ref(false);
const editingCustomer = ref(null);
const draft = ref({});
const dialogError = ref("");

const formDialogErrors = computed(() => ({
  ...errors.value,
  form: dialogError.value,
}));

function openCreate() {
  editingCustomer.value = null;
  dialogError.value = "";
  draft.value = {
    name: "",
    email: "",
    phone: "",
    website: "",
    notes: "",
    is_active: true,
  };
  dialogVisible.value = true;
}

function openEdit(row) {
  editingCustomer.value = row;
  dialogError.value = "";
  draft.value = {
    name: row.name ?? "",
    email: row.email ?? "",
    phone: row.phone ?? "",
    website: row.website ?? "",
    notes: row.notes ?? "",
    is_active: !!row.is_active,
  };
  dialogVisible.value = true;
}

function closeDialog() {
  dialogVisible.value = false;
}

async function submitForm(payload) {
  dialogError.value = "";
  try {
    if (!editingCustomer.value) {
      await create(payload);
    } else {
      await update(editingCustomer.value.id, payload);
    }
    dialogVisible.value = false;
    await load();
  } catch (e) {
    dialogError.value =
      e?.response?.data?.message ?? "Could not save customer.";
  }
}

function confirmDelete(row) {
  confirm.require({
    message: `Delete customer “${row.name}”? This cannot be undone.`,
    header: "Confirm",
    icon: "pi pi-exclamation-triangle",
    rejectProps: { label: "Cancel", severity: "secondary", outlined: true },
    acceptProps: { label: "Delete", severity: "danger" },
    accept: async () => {
      try {
        await remove(row.id);
        await load();
      } catch (e) {
        dialogError.value =
          e?.response?.data?.message ?? "Could not delete customer.";
      }
    },
  });
}

function goShow(row) {
  router.push({ name: "customers-show", params: { id: row.id } });
}

onMounted(async () => {
  await nextTick();
  try {
    await ensureCsrf();
    apiColumnsRaw.value = await getDataTableColumns(RESOURCE_KEY);
  } catch {
    apiColumnsRaw.value = [];
  }
  await load();
});
</script>

<template>
  <BaseIndex flush hide-header>
    <BaseConfirmDialog />

    <B2CDataTable
      table-key="customers.index"
      :columns="columns"
      :rows="rows"
      :loading="loading"
      server-mode
      :total-records="totalRecords"
      :total-all-records="totalAllRecords"
      :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"
      :paginator="true"
      :enable-export="false"
      row-clickable
      resource-label-singular="customer"
      resource-label-plural="customers"
      show-actions
      @row-click="
        ({ data }) =>
          router.push({
            name: 'customers-show',
            params: { id: data.id },
          })
      "
      @update:pagination="
        pagination = $event;
        load();
      "
      @update:sort="
        sort = $event;
        load();
      "
      @update:state="onTableState($event)"
    >
      <template #toolbar-title>
        <div>
          <h1
            class="text-2xl font-semibold tracking-tight text-surface-950 dark:text-surface-0 m-0"
          >
            Customers
          </h1>
          <p
            class="text-sm text-surface-600 dark:text-surface-400 mt-1.5 mb-0 max-w-3xl"
          >
            Companies and contacts in your organisation.
          </p>
        </div>
      </template>
      <template #controls-left>
        <BaseButton
          variant="primary"
          icon="plus"
          label="New Customer"
          class="shrink-0"
          @click="openCreate"
        />
      </template>

      <template #actions="{ row }">
        <div class="flex flex-nowrap items-center justify-end gap-1">
          <BaseButton
            type="button"
            variant="secondary"
            icon="eye"
            text
            rounded
            size="small"
            class="shrink-0"
            :icon-only="true"
            aria-label="Open customer"
            @click.stop="goShow(row)"
          />
          <BaseButton
            type="button"
            variant="secondary"
            icon="pencil"
            text
            rounded
            size="small"
            class="shrink-0"
            :icon-only="true"
            aria-label="Edit customer"
            @click.stop="openEdit(row)"
          />
          <BaseButton
            type="button"
            variant="danger"
            icon="trash"
            text
            rounded
            size="small"
            class="shrink-0"
            :icon-only="true"
            aria-label="Delete customer"
            @click.stop="confirmDelete(row)"
          />
        </div>
      </template>
    </B2CDataTable>

    <CustomerForm
      v-model:visible="dialogVisible"
      :draft="draft"
      :saving="saving"
      :errors="formDialogErrors"
      :title="editingCustomer ? 'Edit customer' : 'New customer'"
      @submit="submitForm"
      @cancel="closeDialog"
    />
  </BaseIndex>
</template>
