-- +goose Up

CREATE TABLE IF NOT EXISTS b2b_language (
  id                INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  created_at        DATETIME(6) NOT NULL,
  updated_at        DATETIME(6) NULL,
  deleted_at        DATETIME(6) NULL,
  name              VARCHAR(128) NOT NULL,
  iso_code          VARCHAR(2) NOT NULL,
  lang_code         VARCHAR(5) NOT NULL,
  date_format       VARCHAR(32) NOT NULL,
  date_format_short VARCHAR(32) NOT NULL,
  rtl               TINYINT(1) NOT NULL DEFAULT 0,
  is_default        TINYINT(1) NOT NULL DEFAULT 0,
  active            TINYINT(1) NOT NULL DEFAULT 1,
  flag              VARCHAR(16) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE INDEX IF NOT EXISTS idx_language_deleted_at
ON b2b_language (deleted_at);

CREATE TABLE IF NOT EXISTS b2b_components (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE UNIQUE INDEX IF NOT EXISTS uk_components_name ON b2b_components (name, id);
-- scopes
CREATE TABLE IF NOT EXISTS b2b_scopes (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE UNIQUE INDEX IF NOT EXISTS uk_scopes_name ON b2b_scopes (name);
-- translations
CREATE TABLE IF NOT EXISTS b2b_translations (
  lang_id INT UNSIGNED NOT NULL,
  scope_id INT UNSIGNED NOT NULL,
  component_id INT UNSIGNED NOT NULL,
  `key` VARCHAR(255) NOT NULL,
  data TEXT NULL,
  PRIMARY KEY (lang_id, scope_id, component_id, `key`),
  CONSTRAINT fk_translations_language FOREIGN KEY (lang_id) REFERENCES b2b_language(id) ON DELETE RESTRICT ON UPDATE RESTRICT,
  CONSTRAINT fk_translations_scope FOREIGN KEY (scope_id) REFERENCES b2b_scopes(id) ON DELETE RESTRICT ON UPDATE RESTRICT,
  CONSTRAINT fk_translations_component FOREIGN KEY (component_id) REFERENCES b2b_components(id) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

CREATE TABLE `b2b_roles` ( 
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(63) NULL
);

CREATE TABLE b2b_permissions (
    `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `name` VARCHAR(255) NOT NULL UNIQUE
);

CREATE TABLE b2b_role_permissions (
    role_id BIGINT UNSIGNED NOT NULL,
    permission_id BIGINT UNSIGNED NOT NULL,

    PRIMARY KEY (role_id, permission_id),

    CONSTRAINT fk_role_permissions_role
        FOREIGN KEY (role_id)
        REFERENCES b2b_roles(id)
        ON DELETE CASCADE,

    CONSTRAINT fk_role_permissions_permission
        FOREIGN KEY (permission_id)
        REFERENCES b2b_permissions(id)
        ON DELETE CASCADE
);

CREATE TABLE `b2b_top_menu_roles` ( 
  `top_menu_id` INT NOT NULL,
  `role_id` BIGINT UNSIGNED NOT NULL,

   PRIMARY KEY (`top_menu_id`, `role_id`),

  CONSTRAINT fk_top_menu_roles_menu
    FOREIGN KEY (`top_menu_id`)
    REFERENCES `b2b_top_menu`(`menu_id`)
    ON DELETE CASCADE,

  CONSTRAINT fk_top_menu_roles_role
    FOREIGN KEY (`role_id`)
    REFERENCES `b2b_roles`(`id`)
    ON DELETE CASCADE
);

-- customers
CREATE TABLE IF NOT EXISTS b2b_customers (
  id                             BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  email                          VARCHAR(255) NOT NULL,
  password                       VARCHAR(255) NULL,
  first_name                     VARCHAR(100) NULL,
  last_name                      VARCHAR(100) NULL,
  role_id                         BIGINT UNSIGNED NOT NULL DEFAULT 1,
  provider                       VARCHAR(20) NULL DEFAULT 'local',
  provider_id                    VARCHAR(255) NULL,
  avatar_url                      VARCHAR(500) NULL,
  is_active                       TINYINT(1) NULL DEFAULT 1,
  email_verified                  TINYINT(1) NULL DEFAULT 0,
  email_verification_token        VARCHAR(255) NULL,
  email_verification_expires      DATETIME(6) NULL,
  password_reset_token            VARCHAR(255) NULL,
  password_reset_expires          DATETIME(6) NULL,
  webdav_token                    VARCHAR(255) NULL,
  webdav_expires                  DATETIME(6) NULL,
  last_password_reset_request     DATETIME(6) NULL,
  last_login_at                   DATETIME(6) NULL,
  lang_id                         INT NULL DEFAULT 2,
  country_id                      INT NULL DEFAULT 2,
  created_at                      DATETIME(6) NULL,
  updated_at                      DATETIME(6) NULL,
  deleted_at                      DATETIME(6) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE UNIQUE INDEX IF NOT EXISTS idx_customers_email
ON b2b_customers (email);

CREATE INDEX IF NOT EXISTS idx_customers_deleted_at
ON b2b_customers (deleted_at);

CREATE INDEX IF NOT EXISTS idx_customers_webdav_token
ON b2b_customers (webdav_token);

ALTER TABLE b2b_customers
ADD CONSTRAINT fk_customer_role
FOREIGN KEY (role_id) REFERENCES b2b_roles(id);

-- customer_carts
CREATE TABLE IF NOT EXISTS b2b_customer_carts (
  cart_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  user_id BIGINT UNSIGNED NOT NULL,
  name VARCHAR(255) NULL,
  CONSTRAINT fk_customer_carts_customers FOREIGN KEY (user_id) REFERENCES b2b_customers(id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE INDEX IF NOT EXISTS idx_customer_carts_user_id ON b2b_customer_carts (user_id);


-- carts_products
CREATE TABLE IF NOT EXISTS b2b_carts_products (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  cart_id INT UNSIGNED NOT NULL,
  product_id INT UNSIGNED NOT NULL,
  product_attribute_id INT NULL,
  amount INT UNSIGNED NOT NULL,
  CONSTRAINT fk_carts_products_customer_carts FOREIGN KEY (cart_id) REFERENCES b2b_customer_carts (cart_id) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT fk_carts_products_product FOREIGN KEY (product_id) REFERENCES ps_product (id_product) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE INDEX IF NOT EXISTS idx_carts_products_cart_id ON b2b_carts_products (cart_id);


-- favorites
CREATE TABLE IF NOT EXISTS b2b_favorites (
  user_id BIGINT UNSIGNED NOT NULL,
  product_id INT UNSIGNED NOT NULL,
  PRIMARY KEY (user_id, product_id),
  CONSTRAINT fk_favorites_customer FOREIGN KEY (user_id) REFERENCES b2b_customers(id) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT fk_favorites_product FOREIGN KEY (product_id) REFERENCES ps_product(id_product) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;


-- refresh_tokens
CREATE TABLE IF NOT EXISTS b2b_refresh_tokens (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  customer_id BIGINT UNSIGNED NOT NULL,
  token_hash VARCHAR(64) NOT NULL,
  expires_at DATETIME(6) NOT NULL,
  created_at DATETIME(6) NOT NULL,
  CONSTRAINT fk_refresh_tokens_customer FOREIGN KEY (customer_id) REFERENCES b2b_customers(id) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE UNIQUE INDEX IF NOT EXISTS uk_refresh_tokens_token_hash ON b2b_refresh_tokens (token_hash);
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_customer_id ON b2b_refresh_tokens (customer_id);

CREATE TABLE `b2b_currencies` ( 
  `id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
  `ps_id_currency` INT UNSIGNED NOT NULL,
  `is_default` TINYINT NOT NULL,
  `is_active` TINYINT NOT NULL,
   PRIMARY KEY (`id`)
)
ENGINE = InnoDB;

ALTER TABLE `b2b_currencies` ADD CONSTRAINT `FK_b2b_currencies_ps_id_currency` FOREIGN KEY (`ps_id_currency`) REFERENCES `ps_currency` (`id_currency`) ON DELETE CASCADE ON UPDATE CASCADE;

CREATE INDEX `fk_b2b_currencies_ps_currency` 
ON `b2b_currencies` (
  `ps_id_currency` ASC
);

CREATE TABLE `b2b_currency_rates` ( 
  `id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
  `b2b_id_currency` BIGINT UNSIGNED NOT NULL,
  `created_at` DATETIME NOT NULL,
  `conversion_rate` DECIMAL(13,6) NULL DEFAULT NULL ,
   PRIMARY KEY (`id`)
)
ENGINE = InnoDB;
ALTER TABLE `b2b_currency_rates` ADD CONSTRAINT `FK_b2b_currency_rates_b2b_id_currency` FOREIGN KEY (`b2b_id_currency`) REFERENCES `b2b_currencies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

CREATE INDEX `fk_b2b_currency_rates_b2b_currencies` 
ON `b2b_currency_rates` (
  `b2b_id_currency` ASC
);

-- countries
CREATE TABLE IF NOT EXISTS b2b_countries (
  `id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
  `flag` VARCHAR(16) NOT NULL,
  `ps_id_country` INT UNSIGNED NOT NULL,
  `b2b_id_currency` BIGINT UNSIGNED NOT NULL,
   PRIMARY KEY (`id`),
  CONSTRAINT `fk_b2b_countries_ps_country` FOREIGN KEY (`ps_id_country`) REFERENCES `ps_country` (`id_country`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `FK_b2b_countries_b2b_id_currency` FOREIGN KEY (`b2b_id_currency`) REFERENCES `b2b_currencies` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
)
ENGINE = InnoDB;
CREATE INDEX `fk_b2b_countries_ps_country` 
ON `b2b_countries` (
  `ps_id_country` ASC
);

-- addresses
CREATE TABLE IF NOT EXISTS b2b_addresses (
  id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
  b2b_customer_id BIGINT UNSIGNED NOT NULL,
  address_info TEXT NOT NULL,
  b2b_country_id BIGINT UNSIGNED NOT NULL,
   PRIMARY KEY (id),
  CONSTRAINT fk_b2b_addresses_b2b_customers FOREIGN KEY (b2b_customer_id) REFERENCES b2b_customers (id) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT fk_b2b_addresses_b2b_countries FOREIGN KEY (b2b_country_id) REFERENCES b2b_countries (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB;


CREATE TABLE b2b_specific_price (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  created_at DATETIME NULL,
  updated_at DATETIME NULL,
  deleted_at DATETIME NULL,
  scope ENUM('shop', 'category', 'product') NOT NULL,
  valid_from DATETIME NULL,
  valid_till DATETIME NULL,
  has_expiration_date BOOLEAN DEFAULT FALSE,
  reduction_type ENUM('amount', 'percentage') NOT NULL,
  price DECIMAL(10, 2) NULL,
  b2b_id_currency BIGINT UNSIGNED NULL, -- specifies which currency is used for the price
  percentage_reduction DECIMAL(5, 2) NULL,
  from_quantity INT UNSIGNED DEFAULT 1,
  is_active BOOLEAN DEFAULT TRUE
) ENGINE = InnoDB;
CREATE INDEX idx_b2b_scope ON b2b_specific_price(scope);
CREATE INDEX idx_b2b_active_dates ON b2b_specific_price(is_active, valid_from, valid_till);
CREATE INDEX idx_b2b_lookup 
ON b2b_specific_price (
  scope,
  is_active,
  from_quantity
);

CREATE TABLE b2b_specific_price_product (
  b2b_specific_price_id BIGINT UNSIGNED,
  id_product INT UNSIGNED,
  PRIMARY KEY (b2b_specific_price_id, id_product),
  FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE,
  FOREIGN KEY (id_product) REFERENCES ps_product(id_product) ON DELETE CASCADE
);

CREATE TABLE b2b_specific_price_category (
  b2b_specific_price_id BIGINT UNSIGNED,
  id_category INT UNSIGNED,
  PRIMARY KEY (b2b_specific_price_id, id_category),
  FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE,
  FOREIGN KEY (id_category) REFERENCES ps_category(id_category) ON DELETE CASCADE
);

CREATE TABLE b2b_specific_price_product_attribute (
  b2b_specific_price_id BIGINT UNSIGNED,
  id_product_attribute INT UNSIGNED,
  PRIMARY KEY (b2b_specific_price_id, id_product_attribute),
  FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE,
  FOREIGN KEY (id_product_attribute) REFERENCES ps_product_attribute(id_product_attribute) ON DELETE CASCADE
);

CREATE TABLE b2b_specific_price_customer (
  b2b_specific_price_id BIGINT UNSIGNED,
  b2b_id_customer BIGINT UNSIGNED,
  PRIMARY KEY (b2b_specific_price_id, b2b_id_customer),
  FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE,
  FOREIGN KEY (b2b_id_customer) REFERENCES b2b_customers(id) ON DELETE CASCADE
);

CREATE TABLE b2b_specific_price_country (
  b2b_specific_price_id BIGINT UNSIGNED,
  b2b_id_country BIGINT UNSIGNED,
  PRIMARY KEY (b2b_specific_price_id, b2b_id_country),
  FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE,
  FOREIGN KEY (b2b_id_country) REFERENCES b2b_countries(id) ON DELETE CASCADE
);

CREATE INDEX idx_b2b_product_rel 
ON b2b_specific_price_product (id_product);

CREATE INDEX idx_b2b_category_rel 
ON b2b_specific_price_category (id_category);

CREATE INDEX idx_b2b_product_attribute_rel 
ON b2b_specific_price_product_attribute (id_product_attribute);

CREATE INDEX idx_bsp_customer 
ON b2b_specific_price_customer (b2b_specific_price_id, b2b_id_customer);

CREATE INDEX idx_bsp_country 
ON b2b_specific_price_country (b2b_specific_price_id, b2b_id_country);

DELIMITER //

CREATE FUNCTION IF NOT EXISTS slugify_eu(input TEXT)
RETURNS TEXT
DETERMINISTIC
BEGIN
    DECLARE s TEXT;

    SET s = LOWER(input);

    -- spaces
    SET s = REPLACE(s,' ','_');

    -- Polish
    SET s = REPLACE(s,'ą','a');
    SET s = REPLACE(s,'ć','c');
    SET s = REPLACE(s,'ę','e');
    SET s = REPLACE(s,'ł','l');
    SET s = REPLACE(s,'ń','n');
    SET s = REPLACE(s,'ó','o');
    SET s = REPLACE(s,'ś','s');
    SET s = REPLACE(s,'ż','z');
    SET s = REPLACE(s,'ź','z');

    -- German
    SET s = REPLACE(s,'ä','a');
    SET s = REPLACE(s,'ö','o');
    SET s = REPLACE(s,'ü','u');
    SET s = REPLACE(s,'ß','ss');

    -- French
    SET s = REPLACE(s,'à','a');
    SET s = REPLACE(s,'â','a');
    SET s = REPLACE(s,'æ','ae');
    SET s = REPLACE(s,'ç','c');
    SET s = REPLACE(s,'è','e');
    SET s = REPLACE(s,'é','e');
    SET s = REPLACE(s,'ê','e');
    SET s = REPLACE(s,'ë','e');
    SET s = REPLACE(s,'î','i');
    SET s = REPLACE(s,'ï','i');
    SET s = REPLACE(s,'ô','o');
    SET s = REPLACE(s,'ù','u');
    SET s = REPLACE(s,'û','u');
    SET s = REPLACE(s,'ü','u');
    SET s = REPLACE(s,'ÿ','y');

    -- Spanish / Portuguese
    SET s = REPLACE(s,'á','a');
    SET s = REPLACE(s,'í','i');
    SET s = REPLACE(s,'ñ','n');

    -- Scandinavian
    SET s = REPLACE(s,'å','a');
    SET s = REPLACE(s,'ø','o');

    RETURN s;
END //

DELIMITER ;


DELIMITER $$

CREATE FUNCTION IF NOT EXISTS get_subcategories(startCategory INT)
RETURNS TEXT
DETERMINISTIC
BEGIN
    DECLARE result TEXT;

    -- Use GROUP_CONCAT to aggregate all IDs into a single string
    WITH RECURSIVE subcategories AS (
        SELECT c.id_category
        FROM ps_category c
        WHERE c.id_category = startCategory

        UNION ALL

        SELECT c.id_category
        FROM ps_category c
        INNER JOIN subcategories sc ON c.id_parent = sc.id_category
    )
    SELECT GROUP_CONCAT(id_category) INTO result
    FROM subcategories;

    RETURN result;
END$$

DELIMITER ;

-- +goose Down

DROP TABLE IF EXISTS b2b_countries;
DROP TABLE IF EXISTS b2b_language;
DROP TABLE IF EXISTS b2b_components;
DROP TABLE IF EXISTS b2b_scopes;
DROP TABLE IF EXISTS b2b_translations;
DROP TABLE IF EXISTS b2b_customers;
DROP TABLE IF EXISTS b2b_refresh_tokens;
DROP TABLE IF EXISTS b2b_currencies;
DROP TABLE IF EXISTS b2b_currency_rates;
DROP TABLE IF EXISTS b2b_specific_price;
DROP TABLE IF EXISTS b2b_specific_price_product;
DROP TABLE IF EXISTS b2b_specific_price_category;
DROP TABLE IF EXISTS b2b_specific_price_product_attribute;
