// @ts-nocheck
export const catalogMakerSql = {
  manufacturers: `
    SELECT id_manufacturer, name
    FROM ps_manufacturer
    ORDER BY name ASC
  `,
  manufacturerByName: `
    SELECT id_manufacturer
    FROM ps_manufacturer
    WHERE name = ?
  `,
  languages: `
    SELECT id_lang, name, iso_code
    FROM ps_lang
    ORDER BY name ASC
  `,
};

export function prepareManufacturerCatalogSqls({ manufacturerId }) {
  const safeManufacturerId = parsePositiveInteger(manufacturerId, "manufacturerId");

  return [
    `
      UPDATE ps_product_catalog pc
      SET pc.skladovka = 0,
          pc.catalog_9b = 0
      WHERE pc.id_manufacturer = ${safeManufacturerId}
    `,
    `
      UPDATE ps_product_catalog pc
      JOIN ps_import_suppliers_dump isd ON isd.ean = pc.ean_13
      SET pc.skladovka = 1
      WHERE pc.id_manufacturer = ${safeManufacturerId}
    `,
    `
      UPDATE ps_product_catalog pc
      SET pc.catalog_9b = 1
      WHERE pc.id_manufacturer = ${safeManufacturerId}
        AND pc.ean_13 IN (
          SELECT pa.ean13
          FROM ps_product_attribute pa
          JOIN ps_product p ON p.id_product = pa.id_product
          WHERE p.id_manufacturer = ${safeManufacturerId}
        )
    `,
  ];
}

export function productToDoByManufacturerSql({ manufacturerId, position = 1 }) {
  const safeManufacturerId = parsePositiveInteger(manufacturerId, "manufacturerId");
  const safePosition = Number.parseInt(position, 10) || 1;

  return `
    WITH todo_refs AS (
      SELECT
        supplier_reference,
        ROW_NUMBER() OVER (ORDER BY MIN(id_product_catalog) ASC) AS position,
        COUNT(*) OVER () AS total
      FROM ps_product_catalog
      WHERE id_manufacturer = ${safeManufacturerId}
        AND catalog_9b = 0
        AND skladovka = 1
      GROUP BY supplier_reference
    ),
    target_ref AS (
      SELECT supplier_reference, position, total
      FROM todo_refs
      WHERE position = ${safePosition}
    ),
    combination AS (
      SELECT pc.*
      FROM ps_product_catalog pc
      JOIN target_ref tr ON tr.supplier_reference = pc.supplier_reference
      WHERE pc.id_manufacturer = ${safeManufacturerId}
        AND pc.catalog_9b = 0
        AND pc.skladovka = 1
      ORDER BY pc.id_product_catalog ASC
      LIMIT 1
    ),
    existing_product AS (
      SELECT pc.supplier_reference, pc.ean_13
      FROM ps_product_catalog pc
      JOIN target_ref tr ON tr.supplier_reference = pc.supplier_reference
      WHERE pc.id_manufacturer = ${safeManufacturerId}
        AND pc.catalog_9b = 1
        AND (pc.skladovka = 1 OR pc.skladovka = 0)
      ORDER BY pc.id_product_catalog ASC
    )
    SELECT
      co.*,
      tr.position,
      tr.total,
      p.id_product,
      p.price,
      (
        SELECT ${prestaImageUrl("i.id_image", "home_default")}
        FROM ps_image i
        WHERE i.id_product = p.id_product
        ORDER BY i.cover DESC, i.position ASC
        LIMIT 1
      ) AS image_url
    FROM combination co
    JOIN target_ref tr ON tr.supplier_reference = co.supplier_reference
    LEFT JOIN existing_product ep ON ep.supplier_reference = co.supplier_reference
    LEFT JOIN ps_product_attribute pa ON pa.ean13 = ep.ean_13
    LEFT JOIN ps_product p ON p.id_product = pa.id_product
    LIMIT 1
  `;
}

export function productByEanSql({ manufacturerId, ean }) {
  const safeManufacturerId = parsePositiveInteger(manufacturerId, "manufacturerId");
  const safeEan = escapeSqlString(normalizeEan(ean));

  if (!safeEan) {
    throw new Error("ean is required.");
  }

  return `
    WITH todo_refs AS (
      SELECT
        supplier_reference,
        ROW_NUMBER() OVER (ORDER BY MIN(id_product_catalog) ASC) AS position,
        COUNT(*) OVER () AS total
      FROM ps_product_catalog
      WHERE id_manufacturer = ${safeManufacturerId}
        AND catalog_9b = 0
        AND skladovka = 1
      GROUP BY supplier_reference
    ),
    combination AS (
      SELECT pc.*
      FROM ps_product_catalog pc
      WHERE pc.id_manufacturer = ${safeManufacturerId}
        AND pc.ean_13 = '${safeEan}'
      ORDER BY pc.id_product_catalog ASC
      LIMIT 1
    ),
    existing_product AS (
      SELECT pc.supplier_reference, pc.ean_13
      FROM ps_product_catalog pc
      JOIN combination co ON co.supplier_reference = pc.supplier_reference
      WHERE pc.id_manufacturer = ${safeManufacturerId}
        AND pc.catalog_9b = 1
      ORDER BY pc.id_product_catalog ASC
    )
    SELECT
      co.*,
      tr.position,
      tr.total,
      p.id_product,
      p.price,
      (
        SELECT ${prestaImageUrl("i.id_image", "home_default")}
        FROM ps_image i
        WHERE i.id_product = p.id_product
        ORDER BY i.cover DESC, i.position ASC
        LIMIT 1
      ) AS image_url
    FROM combination co
    LEFT JOIN todo_refs tr ON tr.supplier_reference = co.supplier_reference
    LEFT JOIN existing_product ep ON ep.supplier_reference = co.supplier_reference
    LEFT JOIN ps_product_attribute pa ON pa.ean13 = ep.ean_13
    LEFT JOIN ps_product p ON p.id_product = pa.id_product
    LIMIT 1
  `;
}

export function productCombinationsByReferenceSql({ manufacturerId, supplierReference }) {
  const safeManufacturerId = parsePositiveInteger(manufacturerId, "manufacturerId");
  const safeSupplierReference = escapeSqlString(supplierReference);

  if (!safeSupplierReference) {
    throw new Error("supplierReference is required.");
  }

  return `
    SELECT pc.*
    FROM ps_product_catalog pc
    WHERE pc.id_manufacturer = ${safeManufacturerId}
      AND pc.supplier_reference = '${safeSupplierReference}'
    ORDER BY pc.id_product_catalog ASC
  `;
}

export function productCombinationInfoSql({ productId, manufacturerId, supplierReference }) {
  const safeProductId = parsePositiveInteger(productId, "productId");
  const safeManufacturerId = parsePositiveInteger(manufacturerId, "manufacturerId");
  const safeSupplierReference = escapeSqlString(supplierReference);

  if (!safeSupplierReference) {
    throw new Error("supplierReference is required.");
  }

  return `
    WITH catalog_rows AS (
      SELECT pc.*
      FROM ps_product_catalog pc
      WHERE pc.id_manufacturer = ${safeManufacturerId}
        AND pc.supplier_reference = '${safeSupplierReference}'
    ),
    attribute_group AS (
      SELECT a.id_attribute_group
      FROM ps_product_attribute pa
      JOIN ps_product_attribute_combination pac
        ON pac.id_product_attribute = pa.id_product_attribute
      JOIN ps_attribute a
        ON a.id_attribute = pac.id_attribute
      JOIN ps_attribute_group_lang agl
        ON agl.id_attribute_group = a.id_attribute_group
      WHERE a.id_attribute_group <> 1
        AND agl.id_lang = 1
        AND pa.id_product = ${safeProductId}
      GROUP BY a.id_attribute_group
      ORDER BY a.id_attribute_group ASC
      LIMIT 1
    ),
    matched_attributes AS (
      SELECT
        cr.id_product_catalog,
        (
          SELECT a.id_attribute
          FROM ps_attribute_lang al
          JOIN ps_attribute a
            ON a.id_attribute = al.id_attribute
          WHERE al.name = TRIM(SUBSTRING_INDEX(cr.color, '/', 1))
            AND al.id_lang = 1
            AND a.id_attribute_group = 1
          ORDER BY a.id_attribute ASC
          LIMIT 1
        ) AS color_attribute_id,
        (
          SELECT al.name
          FROM ps_attribute_lang al
          JOIN ps_attribute a
            ON a.id_attribute = al.id_attribute
          WHERE al.name = TRIM(SUBSTRING_INDEX(cr.color, '/', 1))
            AND al.id_lang = 1
            AND a.id_attribute_group = 1
          ORDER BY a.id_attribute ASC
          LIMIT 1
        ) AS color_name,
        (
          SELECT a.id_attribute
          FROM ps_attribute_lang al
          JOIN ps_attribute a
            ON a.id_attribute = al.id_attribute
          JOIN attribute_group ag
            ON ag.id_attribute_group = a.id_attribute_group
          WHERE al.name = REPLACE(TRIM(cr.combination), ',', '.')
            AND al.id_lang = 1
          ORDER BY a.id_attribute ASC
          LIMIT 1
        ) AS combi_attribute_id,
        (
          SELECT al.name
          FROM ps_attribute_lang al
          JOIN ps_attribute a
            ON a.id_attribute = al.id_attribute
          JOIN attribute_group ag
            ON ag.id_attribute_group = a.id_attribute_group
          WHERE al.name = REPLACE(TRIM(cr.combination), ',', '.')
            AND al.id_lang = 1
          ORDER BY a.id_attribute ASC
          LIMIT 1
        ) AS combi_name
      FROM catalog_rows cr
    ),
    existing_combinations AS (
      SELECT
        ma.id_product_catalog,
        pa.id_product_attribute,
        pa.ean13
      FROM matched_attributes ma
      JOIN ps_product_attribute_combination pac_color
        ON pac_color.id_attribute = ma.color_attribute_id
      JOIN ps_product_attribute_combination pac_combi
        ON pac_combi.id_product_attribute = pac_color.id_product_attribute
       AND pac_combi.id_attribute = ma.combi_attribute_id
      JOIN ps_product_attribute pa
        ON pa.id_product_attribute = pac_color.id_product_attribute
       AND pa.id_product = ${safeProductId}
    )
    SELECT
      cr.id_product_catalog,
      cr.ean_13 AS catalog_ean13,
      ma.color_attribute_id,
      ma.color_name,
      ma.combi_attribute_id,
      ma.combi_name,
      ec.id_product_attribute,
      ec.ean13 AS nine_b_ean13,
      ROUND(cr.wholesale_price * (1 - (CAST(cr.voc_discount AS DECIMAL(10, 4)) / 100)), 0)
        AS nine_b_voc,
      ROUND(cr.moc_price * (1 - (CAST(cr.max_moc_dicount AS DECIMAL(10, 4)) / 100)), 0)
        AS nine_b_moc,
      CASE
        WHEN cr.skladovka = 1
         AND (
           ma.color_attribute_id IS NULL
           OR ma.combi_attribute_id IS NULL
           OR ec.id_product_attribute IS NULL
           OR ec.ean13 <> cr.ean_13
         )
        THEN 1
        ELSE 0
      END AS has_problem
    FROM catalog_rows cr
    LEFT JOIN matched_attributes ma
      ON ma.id_product_catalog = cr.id_product_catalog
    LEFT JOIN existing_combinations ec
      ON ec.id_product_catalog = cr.id_product_catalog
    ORDER BY cr.id_product_catalog ASC
  `;
}

export function suggestedProductsSql({ manufacturerId, supplierReference, productName }) {
  const safeManufacturerId = parsePositiveInteger(manufacturerId, "manufacturerId");
  const safeSupplierReference = escapeSqlLike(supplierReference);
  const safeProductName = escapeSqlLike(productName);

  if (!safeSupplierReference && !safeProductName) {
    throw new Error("supplierReference or productName is required.");
  }

  const conditions = [];
  if (safeSupplierReference) {
    conditions.push(`p.supplier_reference LIKE '%${safeSupplierReference}%'`);
  }
  if (safeProductName) {
    conditions.push(`pl.name LIKE '%${safeProductName}%'`);
  }

  return `
    SELECT
      p.id_product,
      pl.name,
      p.supplier_reference,
      p.active,
      (
        SELECT ${prestaImageUrl("i.id_image", "cart_default")}
        FROM ps_image i
        WHERE i.id_product = p.id_product
        ORDER BY i.cover DESC, i.position ASC
        LIMIT 1
      ) AS image_url
    FROM ps_product p
    JOIN ps_product_lang pl
      ON pl.id_product = p.id_product
     AND pl.id_lang = 1
    WHERE p.id_manufacturer = ${safeManufacturerId}
      AND (${conditions.join(" OR ")})
    ORDER BY p.active DESC, p.id_product DESC
    LIMIT 20
  `;
}

export function mappingSourceTablesSql() {
  return `
    SELECT table_name
    FROM information_schema.tables
    WHERE table_schema = DATABASE()
      AND table_name IN (
        'scrape_sources',
        'scrape_manufacturer_sources',
        'scrape_source_capabilities',
        'scrape_manufacturer_source_capabilities'
      )
    ORDER BY FIELD(
      table_name,
      'scrape_manufacturer_sources',
      'scrape_sources',
      'scrape_manufacturer_source_capabilities',
      'scrape_source_capabilities'
    )
  `;
}

export function mappingSourcesSql({ manufacturerId, scrapeDatabase = "catalog_scrape" }) {
  const safeManufacturerId = parsePositiveInteger(manufacturerId, "manufacturerId");
  const scrapeSchema = escapeSqlIdentifier(scrapeDatabase);

  return `
    SELECT
      ms.id AS mapping_id,
      ms.manufacturer_id AS id_manufacturer,
      s.id AS id_product_catalog_source,
      ms.enabled AS mapping_enabled,
      ms.priority AS mapping_priority,
      s.source_key,
      s.source_name,
      s.source_type,
      s.base_url,
      s.enabled,
      s.priority AS source_priority,
      s.search_primary_key,
      s.search_fallback_keys,
      s.fallback_source_type,
      s.search_url_template,
      s.fallback_url_template,
      s.search_context_keys,
      s.access_mode,
      s.browser_engine,
      s.browser_headless,
      s.wait_after_load_ms,
      s.scraper_config,
      s.note,
      JSON_ARRAYAGG(
        CASE
          WHEN sc.id IS NULL THEN NULL
          ELSE JSON_OBJECT(
            'capability', sc.capability,
            'enabled', COALESCE(msc.enabled, sc.enabled),
            'priority', COALESCE(msc.priority, sc.priority),
            'parserKey', sc.parser_key,
            'parserModule', sc.parser_module,
            'browserEngine', COALESCE(sc.browser_engine, ''),
            'browserHeadless', sc.browser_headless,
            'waitAfterLoadMs', sc.wait_after_load_ms,
            'minWidth', sc.min_width,
            'minHeight', sc.min_height,
            'minLongestSide', sc.min_longest_side,
            'defaultTargetStrategy', sc.default_target_strategy,
            'targetStrategyOverride', COALESCE(msc.target_strategy_override, ''),
            'selectorConfig', sc.selector_config,
            'extractionConfig', sc.extraction_config,
            'qualityConfig', sc.quality_config,
            'configOverride', msc.config_override,
            'note', sc.note
          )
        END
      ) AS capabilities
    FROM ${scrapeSchema}.scrape_manufacturer_sources ms
    JOIN ${scrapeSchema}.scrape_sources s
      ON s.id = ms.source_id
    LEFT JOIN ${scrapeSchema}.scrape_source_capabilities sc
      ON sc.source_id = s.id
     AND sc.enabled = 1
    LEFT JOIN ${scrapeSchema}.scrape_manufacturer_source_capabilities msc
      ON msc.source_capability_id = sc.id
     AND msc.manufacturer_source_id = ms.id
    WHERE ms.manufacturer_id = ${safeManufacturerId}
    GROUP BY
      ms.id,
      ms.manufacturer_id,
      s.id,
      ms.enabled,
      ms.priority,
      s.source_key,
      s.source_name,
      s.source_type,
      s.base_url,
      s.enabled,
      s.priority,
      s.search_primary_key,
      s.search_fallback_keys,
      s.fallback_source_type,
      s.search_url_template,
      s.fallback_url_template,
      s.search_context_keys,
      s.access_mode,
      s.browser_engine,
      s.browser_headless,
      s.wait_after_load_ms,
      s.scraper_config,
      s.note
    ORDER BY
      ms.priority ASC,
      s.priority ASC,
      s.source_name ASC
  `;
}

function escapeSqlIdentifier(value) {
  const text = String(value ?? "").trim();
  if (!/^[a-zA-Z0-9_]+$/.test(text)) {
    throw new Error("SQL identifier contains unsupported characters.");
  }
  return `\`${text}\``;
}

function prestaImageUrl(idExpression, size) {
  const safeSize = String(size ?? "").trim();
  if (!/^[a-zA-Z0-9_]+$/.test(safeSize)) {
    throw new Error("PrestaShop image size contains unsupported characters.");
  }

  const idText = `CAST(${idExpression} AS CHAR)`;
  const pathParts = Array.from({ length: 10 }, (_, index) =>
    `IF(CHAR_LENGTH(${idText}) > ${index}, CONCAT(SUBSTRING(${idText}, ${index + 1}, 1), '/'), '')`,
  ).join(", ");

  return `CONCAT('https://www.9b-plus.com/img/p/', ${pathParts}, ${idExpression}, '-${safeSize}.jpg')`;
}

function escapeSqlString(value) {
  return String(value ?? "").replaceAll("\\", "\\\\").replaceAll("'", "''").trim();
}

function escapeSqlLike(value) {
  return escapeSqlString(value).replaceAll("%", "\\%").replaceAll("_", "\\_");
}

function parsePositiveInteger(value, name) {
  const parsed = Number.parseInt(value, 10);
  if (!Number.isInteger(parsed) || parsed <= 0) {
    throw new Error(`${name} must be a positive integer.`);
  }
  return parsed;
}

function normalizeEan(value) {
  return String(value ?? "").replace(/\D/g, "");
}
