import { api, ensureCsrf } from "../../../services/api.js";
import { getFilterScalar } from "../../../composables/useDataTableFilters.js";
import { ref, unref } from "vue";

/**
 * Server-driven customer list (B2CDataTable serverMode + criteria).
 */
export function useCustomerList() {
  const rows = ref([]);
  const totalRecords = ref(0);
  const totalAllRecords = ref(0);
  const loading = ref(false);
  const error = ref("");

  const pagination = ref({ page: 1, limit: 15 });
  const sort = ref([{ field: "name", order: 1 }]);

  const tableUiState = ref({
    globalSearch: "",
    filters: {},
  });

  let loadTimer = null;
  let fetchSeq = 0;

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

  function scheduleLoad() {
    if (loadTimer) clearTimeout(loadTimer);
    loadTimer = setTimeout(() => {
      loadTimer = null;
      load();
    }, 400);
  }

  function scalarFromFilters(key) {
    const raw = tableUiState.value?.filters?.[key];
    const v = getFilterScalar(raw);
    if (v == null) return "";
    if (Array.isArray(v)) return v.map(String).join(" ").trim();
    return String(v).trim();
  }

  function sortFieldApi(field) {
    const allowed = new Set(["name", "email", "phone", "is_active", "created_at"]);
    return allowed.has(field) ? field : "name";
  }

  async function load() {
    const seq = ++fetchSeq;
    loading.value = true;
    error.value = "";
    try {
      await ensureCsrf();
      const g = String(tableUiState.value?.globalSearch ?? "").trim();

      const activeRaw = scalarFromFilters("is_active");
      let filterActive;
      if (activeRaw === "true" || activeRaw === "1") filterActive = 1;
      else if (activeRaw === "false" || activeRaw === "0") filterActive = 0;

      const s0 = sort.value?.[0];
      const sf = sortFieldApi(s0?.field ?? "name");
      const asc = Number(s0?.order) === 1;

      const { data } = await api.get("/api/customers", {
        params: {
          page: pagination.value.page,
          per_page: pagination.value.limit,
          search: g || undefined,
          filter_active:
            filterActive === 0 || filterActive === 1 ? filterActive : undefined,
          sort_by: sf,
          sort_dir: asc ? "asc" : "desc",
        },
      });
      if (seq !== fetchSeq) return;

      rows.value = data.data ?? [];
      totalRecords.value = data.meta?.total ?? 0;
      totalAllRecords.value = data.meta?.total ?? 0;
    } catch (e) {
      if (seq !== fetchSeq) return;
      error.value =
        e?.response?.data?.message ?? "Could not load customers.";
      rows.value = [];
      totalRecords.value = 0;
    } finally {
      if (seq === fetchSeq) loading.value = false;
    }
  }

  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 };
      scheduleLoad();
    }
  }

  return {
    rows,
    totalRecords,
    totalAllRecords,
    loading,
    error,
    pagination,
    sort,
    load,
    scheduleLoad,
    onTableState,
  };
}

/**
 * Single customer with contacts and addresses.
 */
export function useCustomer(idRef) {
  const customer = ref(null);
  const loading = ref(false);
  const error = ref("");

  async function load() {
    const id = unref(idRef);
    if (id == null || id === "") {
      customer.value = null;

      return;
    }
    loading.value = true;
    error.value = "";
    try {
      await ensureCsrf();
      const { data } = await api.get(`/api/customers/${id}`);
      customer.value = data?.data ?? null;
    } catch (e) {
      error.value = e?.response?.data?.message ?? "Could not load customer.";
      customer.value = null;
    } finally {
      loading.value = false;
    }
  }

  return { customer, loading, error, load };
}

/** Create/update customer payloads. */
export function useCustomerForm() {
  const saving = ref(false);
  const errors = ref({});

  async function create(payload) {
    saving.value = true;
    errors.value = {};
    try {
      await ensureCsrf();
      const { data } = await api.post("/api/customers", payload);
      return data?.data ?? null;
    } catch (e) {
      errors.value = e?.response?.data?.errors ?? {};
      throw e;
    } finally {
      saving.value = false;
    }
  }

  async function update(id, payload) {
    saving.value = true;
    errors.value = {};
    try {
      await ensureCsrf();
      const { data } = await api.patch(`/api/customers/${id}`, payload);
      return data?.data ?? null;
    } catch (e) {
      errors.value = e?.response?.data?.errors ?? {};
      throw e;
    } finally {
      saving.value = false;
    }
  }

  async function remove(id) {
    await ensureCsrf();
    await api.delete(`/api/customers/${id}`);
  }

  return { saving, errors, create, update, remove };
}

export function useCustomerContacts(customerIdRef) {
  const contacts = ref([]);
  const loading = ref(false);
  const error = ref("");

  function customerIdValue() {
    return unref(customerIdRef);
  }

  async function load() {
    const cid = customerIdValue();
    if (cid == null || cid === "") {
      contacts.value = [];
      return;
    }
    loading.value = true;
    error.value = "";
    try {
      await ensureCsrf();
      const { data } = await api.get(`/api/customers/${cid}/contacts`);
      contacts.value = data?.data ?? [];
    } catch (e) {
      error.value =
        e?.response?.data?.message ?? "Could not load contacts.";
      contacts.value = [];
    } finally {
      loading.value = false;
    }
  }

  async function create(payload) {
    const cid = customerIdValue();
    await ensureCsrf();
    const { data } = await api.post(`/api/customers/${cid}/contacts`, payload);
    return data?.data ?? null;
  }

  async function update(contactId, payload) {
    const cid = customerIdValue();
    await ensureCsrf();
    const { data } = await api.patch(
      `/api/customers/${cid}/contacts/${contactId}`,
      payload,
    );
    return data?.data ?? null;
  }

  async function remove(contactId) {
    const cid = customerIdValue();
    await ensureCsrf();
    await api.delete(`/api/customers/${cid}/contacts/${contactId}`);
  }

  return { contacts, loading, error, load, create, update, remove };
}

export function useCustomerAddresses(customerIdRef) {
  const addresses = ref([]);
  const loading = ref(false);
  const error = ref("");

  function customerIdValue() {
    return unref(customerIdRef);
  }

  async function load() {
    const cid = customerIdValue();
    if (cid == null || cid === "") {
      addresses.value = [];
      return;
    }
    loading.value = true;
    error.value = "";
    try {
      await ensureCsrf();
      const { data } = await api.get(`/api/customers/${cid}/addresses`);
      addresses.value = data?.data ?? [];
    } catch (e) {
      error.value =
        e?.response?.data?.message ?? "Could not load addresses.";
      addresses.value = [];
    } finally {
      loading.value = false;
    }
  }

  async function create(payload) {
    const cid = customerIdValue();
    await ensureCsrf();
    const { data } = await api.post(`/api/customers/${cid}/addresses`, payload);
    return data?.data ?? null;
  }

  async function update(addressId, payload) {
    const cid = customerIdValue();
    await ensureCsrf();
    const { data } = await api.patch(
      `/api/customers/${cid}/addresses/${addressId}`,
      payload,
    );
    return data?.data ?? null;
  }

  async function remove(addressId) {
    const cid = customerIdValue();
    await ensureCsrf();
    await api.delete(`/api/customers/${cid}/addresses/${addressId}`);
  }

  return { addresses, loading, error, load, create, update, remove };
}
