-- +goose Up
DELIMITER //

DROP FUNCTION IF EXISTS fn_product_price //
CREATE FUNCTION fn_product_price(
  p_id_product INT UNSIGNED,
  p_id_shop INT UNSIGNED,
  p_id_customer INT UNSIGNED,
  p_id_country INT UNSIGNED,
  p_quantity INT UNSIGNED,
  p_id_product_attribute INT UNSIGNED
)
RETURNS JSON
DETERMINISTIC
READS SQL DATA
BEGIN

  DECLARE v_tax_rate DECIMAL(10,4) DEFAULT 0;
  DECLARE v_tax_group INT;

  DECLARE v_base_raw DECIMAL(20,6);
  DECLARE v_base DECIMAL(20,6);
  DECLARE v_excl DECIMAL(20,6);
  DECLARE v_incl DECIMAL(20,6);

  DECLARE v_reduction_type VARCHAR(20);
  DECLARE v_percentage DECIMAL(10,4);
  DECLARE v_fixed_price DECIMAL(20,6);
  DECLARE v_specific_currency_id BIGINT;

  DECLARE v_has_specific INT DEFAULT 0;

  DECLARE v_target_currency BIGINT;
  DECLARE v_target_rate DECIMAL(13,6) DEFAULT 1;
  DECLARE v_specific_rate DECIMAL(13,6) DEFAULT 1;

  DECLARE v_is_no_vat TINYINT DEFAULT 0;

  SET p_id_product_attribute = NULLIF(p_id_product_attribute, 0);

  -- ================= CUSTOMER VAT =================
  SELECT COALESCE(c.is_no_vat, 0)
  INTO v_is_no_vat
  FROM b2b_customers c
  WHERE c.id = p_id_customer
  LIMIT 1;

  -- ================= TAX GROUP =================
  SELECT ps.id_tax_rules_group
  INTO v_tax_group
  FROM ps_product_shop ps
  WHERE ps.id_product = p_id_product
    AND ps.id_shop = p_id_shop
  LIMIT 1;

  -- ================= TAX =================
  SELECT COALESCE(t.rate, 0)
  INTO v_tax_rate
  FROM ps_tax_rule tr
  JOIN ps_tax t ON t.id_tax = tr.id_tax
  LEFT JOIN b2b_countries c ON c.id = p_id_country
  WHERE tr.id_tax_rules_group = v_tax_group
    AND tr.id_country = c.ps_id_country
  LIMIT 1;

  IF v_is_no_vat = 1 THEN
    SET v_tax_rate = 0;
  END IF;

  -- ================= CURRENCY =================
  SELECT c.b2b_id_currency, r.conversion_rate
  INTO v_target_currency, v_target_rate
  FROM b2b_countries c
  LEFT JOIN b2b_currency_rates r
    ON r.b2b_id_currency = c.b2b_id_currency
  WHERE c.id = p_id_country
  ORDER BY r.created_at DESC
  LIMIT 1;

  -- ================= BASE PRICE =================
  SELECT
    COALESCE(ps.price, p.price) + COALESCE(pas.price, 0)
  INTO v_base_raw
  FROM ps_product p
  LEFT JOIN ps_product_shop ps
    ON ps.id_product = p.id_product AND ps.id_shop = p_id_shop
  LEFT JOIN ps_product_attribute_shop pas
    ON pas.id_product_attribute = p_id_product_attribute
    AND pas.id_shop = p_id_shop
  WHERE p.id_product = p_id_product;

  SET v_base = v_base_raw * v_target_rate;
  SET v_excl = v_base;

  -- ================= RULE SELECTION =================
  SELECT
    1,
    bsp.reduction_type,
    bsp.percentage_reduction,
    bsp.price,
    bsp.b2b_id_currency

  INTO
    v_has_specific,
    v_reduction_type,
    v_percentage,
    v_fixed_price,
    v_specific_currency_id

  FROM b2b_specific_price bsp

  LEFT JOIN b2b_specific_price_product spp
    ON spp.b2b_specific_price_id = bsp.id
    AND spp.id_product = p_id_product

  LEFT JOIN b2b_specific_price_product_attribute spa
    ON spa.b2b_specific_price_id = bsp.id
    AND spa.id_product_attribute = p_id_product_attribute

  LEFT JOIN b2b_specific_price_customer spc
    ON spc.b2b_specific_price_id = bsp.id
    AND spc.b2b_id_customer = p_id_customer

  LEFT JOIN b2b_specific_price_country spco
    ON spco.b2b_specific_price_id = bsp.id
    AND spco.b2b_id_country = p_id_country

  LEFT JOIN b2b_specific_price_category spcat
    ON spcat.b2b_specific_price_id = bsp.id

  LEFT JOIN ps_category_product cp
    ON cp.id_category = spcat.id_category
    AND cp.id_product = p_id_product

  WHERE bsp.is_active = 1
    AND bsp.from_quantity <= p_quantity

    AND (spp.id_product IS NOT NULL OR NOT EXISTS (
          SELECT 1 FROM b2b_specific_price_product x WHERE x.b2b_specific_price_id = bsp.id
        ))

    AND (spa.id_product_attribute IS NOT NULL OR NOT EXISTS (
          SELECT 1 FROM b2b_specific_price_product_attribute x WHERE x.b2b_specific_price_id = bsp.id
        ))

    AND (spc.b2b_id_customer IS NOT NULL OR NOT EXISTS (
          SELECT 1 FROM b2b_specific_price_customer x WHERE x.b2b_specific_price_id = bsp.id
        ))

    AND (spco.b2b_id_country IS NOT NULL OR NOT EXISTS (
          SELECT 1 FROM b2b_specific_price_country x WHERE x.b2b_specific_price_id = bsp.id
        ))

    AND (cp.id_product IS NOT NULL OR NOT EXISTS (
          SELECT 1 FROM b2b_specific_price_category x WHERE x.b2b_specific_price_id = bsp.id
        ))

  ORDER BY
    (spc.b2b_id_customer IS NOT NULL) DESC,
    (spa.id_product_attribute IS NOT NULL) DESC,
    (spp.id_product IS NOT NULL) DESC,
    (cp.id_product IS NOT NULL) DESC,
    (spco.b2b_id_country IS NOT NULL) DESC,
    bsp.id DESC

  LIMIT 1;

  -- ================= APPLY =================
  IF v_has_specific = 1 THEN

    IF v_reduction_type = 'amount' THEN

      IF v_specific_currency_id IS NOT NULL AND v_specific_currency_id != v_target_currency THEN

        SELECT r.conversion_rate
        INTO v_specific_rate
        FROM b2b_currency_rates r
        WHERE r.b2b_id_currency = v_specific_currency_id
        ORDER BY r.created_at DESC
        LIMIT 1;

        SET v_excl = (v_fixed_price / v_specific_rate) * v_target_rate;

      ELSE
        SET v_excl = v_fixed_price;
      END IF;

    ELSEIF v_reduction_type = 'percentage' THEN
      SET v_excl = v_base * (1 - v_percentage / 100);
    END IF;

  END IF;

  SET v_incl = v_excl * (1 + v_tax_rate / 100);

  RETURN JSON_OBJECT(
    'base', v_base,
    'final_tax_excl', v_excl,
    'final_tax_incl', v_incl,
    'tax_rate', v_tax_rate,
    'rate', v_target_rate
  );

END //

DELIMITER ;

DELIMITER //

DROP PROCEDURE IF EXISTS get_product_variants //
CREATE PROCEDURE get_product_variants(
  IN p_id_product INT,
  IN p_id_shop INT,
  IN p_id_lang INT,
  IN p_id_customer INT,
  IN p_id_country INT,
  IN p_quantity INT
)
BEGIN

SELECT
  pa.id_product_attribute,
  pa.reference,

  -- PRICE (computed once per row via correlated subquery)
  CAST(JSON_UNQUOTE(JSON_EXTRACT(
    fn_product_price(
      p_id_product,
      p_id_shop,
      p_id_customer,
      p_id_country,
      p_quantity,
      pa.id_product_attribute
    ),
    '$.base'
  )) AS DECIMAL(20,6)) AS base_price,

  CAST(JSON_UNQUOTE(JSON_EXTRACT(
    fn_product_price(
      p_id_product,
      p_id_shop,
      p_id_customer,
      p_id_country,
      p_quantity,
      pa.id_product_attribute
    ),
    '$.final_tax_excl'
  )) AS DECIMAL(20,6)) AS price_tax_excl,

  CAST(JSON_UNQUOTE(JSON_EXTRACT(
    fn_product_price(
      p_id_product,
      p_id_shop,
      p_id_customer,
      p_id_country,
      p_quantity,
      pa.id_product_attribute
    ),
    '$.final_tax_incl'
  )) AS DECIMAL(20,6)) AS price_tax_incl,

  IFNULL(sa.quantity, 0) AS quantity,

  (
    SELECT JSON_ARRAYAGG(
      JSON_OBJECT(
        'group', agl.name,
        'attribute', al.name
      )
    )
    FROM ps_product_attribute_combination pac
    JOIN ps_attribute a ON a.id_attribute = pac.id_attribute
    JOIN ps_attribute_lang al
      ON al.id_attribute = a.id_attribute AND al.id_lang = p_id_lang
    JOIN ps_attribute_group_lang agl
      ON agl.id_attribute_group = a.id_attribute_group AND agl.id_lang = p_id_lang
    WHERE pac.id_product_attribute = pa.id_product_attribute
  ) AS attributes

FROM ps_product_attribute pa

JOIN ps_product_attribute_shop pas
  ON pas.id_product_attribute = pa.id_product_attribute
 AND pas.id_shop = p_id_shop

LEFT JOIN ps_stock_available sa
  ON sa.id_product = pa.id_product
 AND sa.id_product_attribute = pa.id_product_attribute
 AND sa.id_shop = p_id_shop

WHERE pa.id_product = p_id_product;

END //

DELIMITER ;

DELIMITER //

DROP PROCEDURE IF EXISTS get_product_price //
CREATE PROCEDURE get_product_price(
  IN p_id_product INT,
  IN p_id_shop INT,
  IN p_id_customer INT,
  IN p_id_country INT,
  IN p_quantity INT
)
BEGIN

SELECT fn_product_price(
  p_id_product,
  p_id_shop,
  p_id_customer,
  p_id_country,
  p_quantity,
  NULL
) AS price;

END //

DELIMITER ;

DELIMITER //
DROP PROCEDURE IF EXISTS get_product_base //
CREATE PROCEDURE get_product_base(
  IN p_id_product INT,
  IN p_id_shop INT,
  IN p_id_lang INT,
  IN p_id_customer INT
)
BEGIN
    SELECT
        p.id_product AS id,                                 -- matches view.Product.ID
        
        p.reference,
        p.supplier_reference,
        p.ean13,
        p.upc,
        p.isbn,
        
        -- Price related (basic)
        p.price AS base_price,
        p.wholesale_price,
        p.unity,
        p.unit_price_ratio,
        
        -- Stock & Availability
        p.quantity,
        p.minimal_quantity,
        p.available_for_order,
        p.available_date,
        p.out_of_stock AS out_of_stock_behavior,           -- 0=deny, 1=allow, 2=default
        
        -- Flags
        COALESCE(ps.on_sale, 0) AS on_sale,
        COALESCE(ps.show_price, 1) AS show_price,
        p.condition,
        p.is_virtual,
        
        -- Physical
        p.weight,
        p.width,
        p.height,
        p.depth,
        p.additional_shipping_cost,
        
        -- Delivery
        p.additional_delivery_times AS delivery_days,     -- you can adjust if needed
        
        -- Status
        COALESCE(ps.active, p.active) AS active,
        COALESCE(ps.visibility, p.visibility) AS visibility,
        p.indexed,
        
        -- Other useful
        p.date_add,
        p.date_upd,
        
        -- Language data
        pl.name,
        pl.description,
        pl.description_short,
        
        -- Relations
        m.name AS manufacturer,
        cl.name AS category,

        p.is_oem,
        EXISTS(
          SELECT 1 FROM b2b_favorites f
          WHERE f.user_id = p_id_customer AND f.product_id = p_id_product
        ) AS is_favorite,
        CASE
          WHEN ps.date_add >= DATE_SUB(
            NOW(),
            INTERVAL COALESCE(CAST(ps_configuration.value AS SIGNED), 20) DAY
          ) AND ps.active = 1
          THEN 1
          ELSE 0
        END AS is_new



    FROM ps_product p
    LEFT JOIN ps_product_shop ps 
        ON ps.id_product = p.id_product 
       AND ps.id_shop = p_id_shop
    LEFT JOIN ps_product_lang pl 
        ON pl.id_product = p.id_product 
       AND pl.id_lang = p_id_lang 
       AND pl.id_shop = p_id_shop
    LEFT JOIN ps_category_lang cl 
        ON cl.id_category = COALESCE(ps.id_category_default, p.id_category_default)
       AND cl.id_lang = p_id_lang 
       AND cl.id_shop = p_id_shop
    LEFT JOIN ps_manufacturer m 
        ON m.id_manufacturer = p.id_manufacturer
    LEFT JOIN ps_configuration
        ON ps_configuration.name = PS_NB_DAYS_NEW_PRODUCT

    WHERE p.id_product = p_id_product
    LIMIT 1;
END //
DELIMITER ;

-- +goose Down
