package queries

import (
	"database/sql"
	"fmt"
)

func EnsurePricingCalcInfraTables(pg *sql.DB) error {
	stmts := []string{
		`
CREATE TABLE IF NOT EXISTS mk_fx_rate_cache (
  rate_date         DATE PRIMARY KEY,
  usd_try           NUMERIC(18,6) NOT NULL DEFAULT 0,
  eur_try           NUMERIC(18,6) NOT NULL DEFAULT 0,
  usd_eur           NUMERIC(18,6) NOT NULL DEFAULT 0,
  source_system     TEXT NOT NULL DEFAULT 'MSSQL',
  source_updated_at TIMESTAMPTZ,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT now()
)`,
		`CREATE INDEX IF NOT EXISTS ix_mk_fx_rate_cache_updated_at ON mk_fx_rate_cache (updated_at DESC)`,
		`
CREATE TABLE IF NOT EXISTS mk_price_snapshot (
  id                   UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  product_code         TEXT NOT NULL,
  pricing_parameter_id BIGINT REFERENCES mk_urunpricingprmtr(id) ON DELETE CASCADE,
  rule_id              UUID REFERENCES mk_pricing_rule(id) ON DELETE SET NULL,
  strategy_code        TEXT NOT NULL DEFAULT 'CORE',
  anchor_mode          TEXT NOT NULL DEFAULT 'USD',
  fx_date              DATE NOT NULL,
  cost_date            DATE,
  base_price_try       NUMERIC(18,6) NOT NULL DEFAULT 0,
  base_price_usd       NUMERIC(18,6) NOT NULL DEFAULT 0,
  try1                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  try2                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  try3                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  try4                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  try5                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  try6                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  usd1                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  usd2                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  usd3                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  usd4                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  usd5                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  usd6                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  eur1                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  eur2                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  eur3                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  eur4                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  eur5                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  eur6                 NUMERIC(18,6) NOT NULL DEFAULT 0,
  calc_hash            TEXT NOT NULL DEFAULT '',
  created_at           TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at           TIMESTAMPTZ NOT NULL DEFAULT now(),
  CONSTRAINT uq_mk_price_snapshot_product_scope UNIQUE (product_code, pricing_parameter_id),
  CONSTRAINT ck_mk_price_snapshot_strategy_code CHECK (strategy_code IN ('CORE','PREMIUM','SARTORIAL')),
  CONSTRAINT ck_mk_price_snapshot_anchor_mode CHECK (anchor_mode IN ('TRY','USD'))
)`,
		`CREATE INDEX IF NOT EXISTS ix_mk_price_snapshot_rule ON mk_price_snapshot (rule_id)`,
		`CREATE INDEX IF NOT EXISTS ix_mk_price_snapshot_updated_at ON mk_price_snapshot (updated_at DESC)`,
		`
CREATE TABLE IF NOT EXISTS mk_price_target_map_pg (
  id            BIGSERIAL PRIMARY KEY,
  currency      TEXT NOT NULL,
  level_no      SMALLINT NOT NULL,
  sdprcgrp_id   INTEGER,
  description   TEXT NOT NULL DEFAULT '',
  is_active     BOOLEAN NOT NULL DEFAULT TRUE,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
  CONSTRAINT uq_mk_price_target_map_pg UNIQUE (currency, level_no),
  CONSTRAINT ck_mk_price_target_map_pg_currency CHECK (currency IN ('TRY','USD','EUR')),
  CONSTRAINT ck_mk_price_target_map_pg_level_no CHECK (level_no BETWEEN 1 AND 6)
)`,
		`CREATE INDEX IF NOT EXISTS ix_mk_price_target_map_pg_active ON mk_price_target_map_pg (is_active, currency, level_no)`,
		`
CREATE TABLE IF NOT EXISTS mk_price_target_map_nebim (
  id               BIGSERIAL PRIMARY KEY,
  currency         TEXT NOT NULL,
  level_no         SMALLINT NOT NULL,
  price_group_code TEXT NOT NULL DEFAULT '',
  description      TEXT NOT NULL DEFAULT '',
  is_active        BOOLEAN NOT NULL DEFAULT TRUE,
  created_at       TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at       TIMESTAMPTZ NOT NULL DEFAULT now(),
  CONSTRAINT uq_mk_price_target_map_nebim UNIQUE (currency, level_no),
  CONSTRAINT ck_mk_price_target_map_nebim_currency CHECK (currency IN ('TRY','USD','EUR')),
  CONSTRAINT ck_mk_price_target_map_nebim_level_no CHECK (level_no BETWEEN 1 AND 6)
)`,
		`CREATE INDEX IF NOT EXISTS ix_mk_price_target_map_nebim_active ON mk_price_target_map_nebim (is_active, currency, level_no)`,
		`
CREATE TABLE IF NOT EXISTS mk_price_recalc_queue (
  id                   BIGSERIAL PRIMARY KEY,
  product_code         TEXT NOT NULL,
  pricing_parameter_id BIGINT REFERENCES mk_urunpricingprmtr(id) ON DELETE SET NULL,
  reason               TEXT NOT NULL DEFAULT '',
  status               TEXT NOT NULL DEFAULT 'pending',
  attempts             SMALLINT NOT NULL DEFAULT 0,
  available_at         TIMESTAMPTZ NOT NULL DEFAULT now(),
  queued_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
  processed_at         TIMESTAMPTZ,
  last_error           TEXT NOT NULL DEFAULT '',
  created_at           TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at           TIMESTAMPTZ NOT NULL DEFAULT now(),
  CONSTRAINT ck_mk_price_recalc_queue_status CHECK (status IN ('pending','processing','done','failed'))
)`,
		`CREATE INDEX IF NOT EXISTS ix_mk_price_recalc_queue_status ON mk_price_recalc_queue (status, available_at, queued_at)`,
		`CREATE UNIQUE INDEX IF NOT EXISTS uq_mk_price_recalc_queue_pending ON mk_price_recalc_queue (product_code, COALESCE(pricing_parameter_id, 0)) WHERE status IN ('pending','processing')`,
		`
CREATE TABLE IF NOT EXISTS mk_mmitem_dim_combo (
  product_code TEXT NOT NULL,
  dim1         INTEGER NOT NULL,
  dim3         INTEGER,
  dim3_key     INTEGER GENERATED ALWAYS AS (COALESCE(dim3, 0)) STORED,
  updated_at   TIMESTAMPTZ NOT NULL DEFAULT now(),
  CONSTRAINT pk_mk_mmitem_dim_combo PRIMARY KEY (product_code, dim1, dim3_key)
)`,
		`CREATE INDEX IF NOT EXISTS ix_mk_mmitem_dim_combo_product ON mk_mmitem_dim_combo (product_code, updated_at DESC)`,
		`
CREATE TABLE IF NOT EXISTS mk_dim_token_map (
  dim_column TEXT NOT NULL,  -- dimval1 or dimval3
  token      TEXT NOT NULL,  -- normalized token (e.g. "001", "82", etc.)
  dim_id     INTEGER NOT NULL,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  CONSTRAINT pk_mk_dim_token_map PRIMARY KEY (dim_column, token)
)`,
		`CREATE INDEX IF NOT EXISTS ix_mk_dim_token_map_updated ON mk_dim_token_map (updated_at DESC)`,
	}

	for _, stmt := range stmts {
		if _, err := pg.Exec(stmt); err != nil {
			return err
		}
	}

	if err := seedPricingTargetMapRows(pg, "mk_price_target_map_pg", "sdprcgrp_id"); err != nil {
		return err
	}
	if err := seedPricingTargetMapRows(pg, "mk_price_target_map_nebim", "price_group_code"); err != nil {
		return err
	}

	// Repair invalid/missing pg target mappings after manual edits or table resets.
	// sdprcgrp_id is expected to be 1..6 in this installation.
	if _, err := pg.Exec(`
UPDATE mk_price_target_map_pg
SET sdprcgrp_id = level_no,
    updated_at = now()
WHERE is_active = TRUE
  AND (sdprcgrp_id IS NULL OR sdprcgrp_id NOT BETWEEN 1 AND 6)
`); err != nil {
		return err
	}

	return nil
}

func seedPricingTargetMapRows(pg *sql.DB, tableName string, valueColumn string) error {
	currencies := []string{"TRY", "USD", "EUR"}
	for _, currency := range currencies {
		for level := 1; level <= 6; level++ {
			stmt := fmt.Sprintf(`
INSERT INTO %s (currency, level_no, %s, description, is_active, created_at, updated_at)
VALUES ($1, $2, NULL, '', TRUE, now(), now())
ON CONFLICT (currency, level_no) DO NOTHING
`, tableName, valueColumn)
			// PG targets: default sdprcgrp_id = level_no (1..6). This keeps sdprc writes valid after resets.
			if tableName == "mk_price_target_map_pg" && valueColumn == "sdprcgrp_id" {
				stmt = fmt.Sprintf(`
INSERT INTO %s (currency, level_no, %s, description, is_active, created_at, updated_at)
VALUES ($1, $2::smallint, $2::integer, '', TRUE, now(), now())
ON CONFLICT (currency, level_no) DO NOTHING
`, tableName, valueColumn)
			}
			if valueColumn == "price_group_code" {
				stmt = fmt.Sprintf(`
INSERT INTO %s (currency, level_no, %s, description, is_active, created_at, updated_at)
VALUES ($1, $2, '', '', TRUE, now(), now())
ON CONFLICT (currency, level_no) DO NOTHING
`, tableName, valueColumn)
			}
			if _, err := pg.Exec(stmt, currency, level); err != nil {
				return err
			}
		}
	}
	return nil
}
