import { Injectable, Inject } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { Logger } from "nestjs-pino";
import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service";
import {
  assertSalesforceId,
  assertSoqlFieldName,
} from "@bff/integrations/salesforce/utils/soql.util";
import {
  buildProductQuery,
  buildCatalogServiceQuery,
} from "@bff/integrations/salesforce/utils/catalog-query-builder";
import { getErrorMessage } from "@bff/core/utils/error.util";
import type {
  SalesforceProduct2WithPricebookEntries,
  SalesforcePricebookEntryRecord,
} from "@customer-portal/domain/catalog";
import { Providers as CatalogProviders } from "@customer-portal/domain/catalog";
import type { SalesforceResponse } from "@customer-portal/domain/common";

@Injectable()
export class BaseCatalogService {
  protected readonly portalPriceBookId: string;
  protected readonly portalCategoryField: string;

  constructor(
    protected readonly sf: SalesforceConnection,
    private readonly configService: ConfigService,
    @Inject(Logger) protected readonly logger: Logger
  ) {
    const portalPricebook = this.configService.get<string>("PORTAL_PRICEBOOK_ID")!;
    this.portalPriceBookId = assertSalesforceId(portalPricebook, "PORTAL_PRICEBOOK_ID");
    const portalCategory =
      this.configService.get<string>("PRODUCT_PORTAL_CATEGORY_FIELD") ?? "Product2Categories1__c";
    this.portalCategoryField = assertSoqlFieldName(portalCategory, "PRODUCT_PORTAL_CATEGORY_FIELD");
  }

  protected async executeQuery<TRecord extends SalesforceProduct2WithPricebookEntries>(
    soql: string,
    context: string
  ): Promise<TRecord[]> {
    try {
      const res = (await this.sf.query(soql, {
        label: `catalog:${context.replace(/\s+/g, "_").toLowerCase()}`,
      })) as SalesforceResponse<TRecord>;
      return res.records ?? [];
    } catch (error: unknown) {
      this.logger.error(`Query failed: ${context}`, {
        error: getErrorMessage(error),
        soql,
        context,
      });
      return [];
    }
  }

  protected extractPricebookEntry(
    record: SalesforceProduct2WithPricebookEntries
  ): SalesforcePricebookEntryRecord | undefined {
    const entry = CatalogProviders.Salesforce.extractPricebookEntry(record);
    if (!entry) {
      const sku = record.StockKeepingUnit ?? undefined;
      this.logger.warn(
        `No pricebook entry found for product ${String(record.Name)} (SKU: ${String(sku ?? "")}). Pricebook ID: ${this.portalPriceBookId}.`
      );
      return undefined;
    }

    return entry;
  }

  protected buildProductQuery(
    category: string,
    itemClass: string,
    additionalFields: string[] = [],
    additionalConditions: string = ""
  ): string {
    return buildProductQuery(
      this.portalPriceBookId,
      this.portalCategoryField,
      category,
      itemClass,
      additionalFields,
      additionalConditions
    );
  }

  protected parseJsonField(field: unknown): string[] {
    if (!field) return [];
    if (Array.isArray(field)) return field as string[];
    if (typeof field === "string") {
      try {
        const parsed: unknown = JSON.parse(field);
        return Array.isArray(parsed) ? (parsed as string[]) : [];
      } catch {
        return [];
      }
    }
    return [];
  }

  protected buildCatalogServiceQuery(category: string, additionalFields: string[] = []): string {
    return buildCatalogServiceQuery(
      this.portalPriceBookId,
      this.portalCategoryField,
      category,
      additionalFields
    );
  }
}
