import api from "../axios";

export interface CatalogItemFilters {
  search?: string;
  category?: string | number;
  subcategory?: string | number;
  group?: string;
  manufacturer?: string;
  ecosystem?: string;
  inStock?: boolean;
  minPrice?: number;
  maxPrice?: number;
  includeInactive?: boolean;
}

export interface CategoryTreeEntry {
  name: string;
  type?: string;
  cwId?: number;
  subcategories?: CategoryTreeEntry[];
  entries?: CategoryTreeEntry[];
}

export interface EcosystemManufacturer {
  name: string;
  cwId?: number;
  category?: string;
  subcategoryPrefix?: string;
}

export interface EcosystemEntry {
  name: string;
  manufacturers: EcosystemManufacturer[];
}

export interface CategoryTreeResponse {
  categories: CategoryTreeEntry[];
  ecosystems: EcosystemEntry[];
}

export interface FilterValues {
  categories: string[];
  subcategories: string[];
  manufacturers: string[];
}

export interface CatalogItem {
  id: string;
  identifier?: string;
  cwCatalogId?: number;
  name?: string;
  description?: string;
  quantity?: number;
  partNumber?: string;
  vendorSku?: string;
  manufacturer?: string;
  price?: number;
  cost?: number;
  taxableFlag?: boolean;
  procurementNotes?: string;
  productNarrative?: string;
  customerDescription?: string;
  unitOfMeasure?: string;
  onHand?: number;
  inactive?: boolean;
  category?: string;
  subcategory?: string;
  [key: string]: unknown;
}

/** Map raw API fields to CatalogItem shape (e.g. salesTaxable → taxableFlag) */
function normalizeCatalogItem(raw: Record<string, unknown>): CatalogItem {
  const item = { ...raw } as CatalogItem;
  if (item.taxableFlag == null && raw.salesTaxable != null) {
    item.taxableFlag = raw.salesTaxable as boolean;
  }
  return item;
}

export const procurement = {
  async fetchMany(
    accessToken: string,
    page: number = 1,
    filters: CatalogItemFilters = {},
    rpp: number = 30,
  ) {
    const params: Record<string, unknown> = { page, rpp };
    if (filters.search && filters.search.length > 0)
      params.search = filters.search;
    if (filters.includeInactive) params.includeInactive = true;
    if (filters.category != null && filters.category !== "")
      params.category = filters.category;
    if (filters.subcategory != null && filters.subcategory !== "")
      params.subcategory = filters.subcategory;
    if (filters.group) params.group = filters.group;
    if (filters.manufacturer) params.manufacturer = filters.manufacturer;
    if (filters.ecosystem) params.ecosystem = filters.ecosystem;
    if (filters.inStock) params.inStock = true;
    if (filters.minPrice != null) params.minPrice = filters.minPrice;
    if (filters.maxPrice != null) params.maxPrice = filters.maxPrice;

    const response = await api.get("/v1/procurement/items", {
      params,
      headers: {
        Authorization: `Bearer ${accessToken}`,
      },
    });
    const result = response.data;
    if (Array.isArray(result?.data)) {
      result.data = result.data.map(normalizeCatalogItem);
    }
    return result;
  },

  async fetch(
    accessToken: string,
    identifier: string,
    options?: { includeLinkedItems?: boolean },
  ) {
    const params: Record<string, string> = {};
    if (options?.includeLinkedItems) params.includeLinkedItems = "true";

    const response = await api.get(`/v1/procurement/items/${identifier}`, {
      params,
      headers: {
        Authorization: `Bearer ${accessToken}`,
      },
    });
    const result = response.data;
    if (result?.data && !Array.isArray(result.data)) {
      result.data = normalizeCatalogItem(result.data);
    }
    return result;
  },

  async count(accessToken: string, activeOnly: boolean = false) {
    const params: Record<string, string> = {};
    if (activeOnly) params.activeOnly = "true";

    const response = await api.get("/v1/procurement/count", {
      params,
      headers: {
        Authorization: `Bearer ${accessToken}`,
      },
    });
    return response.data.data.count;
  },

  async fetchInventory(accessToken: string, identifier: string) {
    const response = await api.get(
      `/v1/procurement/items/${identifier}/inventory`,
      {
        params: { includeWarehouse: true },
        headers: {
          Authorization: `Bearer ${accessToken}`,
        },
      },
    );
    return response.data;
  },

  async refreshInventory(accessToken: string, identifier: string) {
    const response = await api.post(
      `/v1/procurement/items/${identifier}/refresh-inventory`,
      {},
      {
        headers: {
          Authorization: `Bearer ${accessToken}`,
        },
      },
    );
    return response.data;
  },

  async fetchLinkedItems(accessToken: string, identifier: string) {
    const response = await api.get(
      `/v1/procurement/items/${identifier}/linked`,
      {
        headers: {
          Authorization: `Bearer ${accessToken}`,
        },
      },
    );
    return response.data;
  },

  async linkItem(accessToken: string, identifier: string, targetId: string) {
    const response = await api.post(
      `/v1/procurement/items/${identifier}/link`,
      { targetId },
      {
        headers: {
          Authorization: `Bearer ${accessToken}`,
        },
      },
    );
    return response.data;
  },

  async unlinkItem(accessToken: string, identifier: string, targetId: string) {
    const response = await api.post(
      `/v1/procurement/items/${identifier}/unlink`,
      { targetId },
      {
        headers: {
          Authorization: `Bearer ${accessToken}`,
        },
      },
    );
    return response.data;
  },

  async fetchCategories(accessToken: string): Promise<CategoryTreeResponse> {
    const response = await api.get("/v1/procurement/categories", {
      headers: {
        Authorization: `Bearer ${accessToken}`,
      },
    });
    return response.data.data;
  },

  async fetchFilters(
    accessToken: string,
    options?: {
      category?: string | number;
      subcategory?: string | number;
      includeInactive?: boolean;
    },
  ): Promise<FilterValues> {
    const params: Record<string, string | number> = {};
    if (options?.category != null && options.category !== "")
      params.category = options.category;
    if (options?.subcategory != null && options.subcategory !== "")
      params.subcategory = options.subcategory;
    if (options?.includeInactive) params.includeInactive = "true";

    const response = await api.get("/v1/procurement/filters", {
      params,
      headers: {
        Authorization: `Bearer ${accessToken}`,
      },
    });
    return response.data.data;
  },
};
