package mysql

import (
	"context"
	"database/sql"
	"errors"
	"strings"

	mysqlDriver "github.com/go-sql-driver/mysql"
)

func ensureResourceShopPurchaseOrderIndexes(ctx context.Context, db *sql.DB) error {

	if _, err := db.ExecContext(ctx, `
		ALTER TABLE resource_shop_purchase_orders
		ADD INDEX idx_resource_shop_purchase_time (app_code, created_at_ms, order_id)`); err != nil && !isDuplicateKeyNameError(err) {
		return err
	}

	if _, err := db.ExecContext(ctx, `
		ALTER TABLE resource_shop_purchase_orders
		ADD INDEX idx_resource_shop_purchase_resource_time (app_code, resource_id, created_at_ms, order_id)`); err != nil && !isDuplicateKeyNameError(err) {
		return err
	}
	return nil
}

func ensureResourceGrantRevokeSchema(ctx context.Context, db *sql.DB) error {
	if _, err := db.ExecContext(ctx, `
		ALTER TABLE resource_grants
		ADD COLUMN revoked_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '撤销时间，UTC epoch ms' AFTER operator_user_id`); err != nil && !isDuplicateColumnError(err) {
		return err
	}
	if _, err := db.ExecContext(ctx, `
		ALTER TABLE resource_grants
		ADD COLUMN revoked_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '撤销操作人用户 ID' AFTER revoked_at_ms`); err != nil && !isDuplicateColumnError(err) {
		return err
	}
	if _, err := db.ExecContext(ctx, `
		ALTER TABLE resource_grants
		ADD COLUMN revoke_reason VARCHAR(256) NOT NULL DEFAULT '' COMMENT '撤销原因' AFTER revoked_by_user_id`); err != nil && !isDuplicateColumnError(err) {
		return err
	}
	return nil
}

func isDuplicateKeyNameError(err error) bool {
	var mysqlErr *mysqlDriver.MySQLError
	return errors.As(err, &mysqlErr) && mysqlErr.Number == 1061
}

func ensureHostSalarySettlementSchema(ctx context.Context, db *sql.DB) error {

	if _, err := db.ExecContext(ctx, `
		ALTER TABLE host_salary_settlement_records
		ADD COLUMN trigger_mode VARCHAR(24) NOT NULL DEFAULT 'automatic' COMMENT '触发方式：automatic/manual' AFTER settlement_type`); err != nil && !isDuplicateColumnError(err) {
		return err
	}

	if _, err := db.ExecContext(ctx, `
		ALTER TABLE host_salary_settlement_records
		ADD COLUMN settlement_role VARCHAR(24) NOT NULL DEFAULT 'all' COMMENT '结算身份：all/host/agency' AFTER trigger_mode`); err != nil && !isDuplicateColumnError(err) {
		return err
	}
	return nil
}

func ensureExternalRechargeSchema(ctx context.Context, db *sql.DB) error {
	if _, err := db.ExecContext(ctx, `
		ALTER TABLE wallet_recharge_products
		ADD COLUMN audience_type VARCHAR(32) NOT NULL DEFAULT 'normal' COMMENT '充值档位适用用户类型：normal/coin_seller' AFTER app_code`); err != nil && !isDuplicateColumnError(err) {
		return err
	}
	if _, err := db.ExecContext(ctx, `
		CREATE TABLE IF NOT EXISTS third_party_payment_channels (
		  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
		  provider_code VARCHAR(32) NOT NULL COMMENT '三方支付渠道编码',
		  provider_name VARCHAR(64) NOT NULL COMMENT '三方支付渠道名称',
		  status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '状态：active/disabled',
		  sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重',
		  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
		  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
		  PRIMARY KEY (app_code, provider_code),
		  KEY idx_third_party_payment_channels_status (app_code, status, sort_order)
		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='三方支付渠道配置表'`); err != nil {
		return err
	}
	if _, err := db.ExecContext(ctx, `
		CREATE TABLE IF NOT EXISTS third_party_payment_methods (
		  method_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '支付方式 ID',
		  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
		  provider_code VARCHAR(32) NOT NULL COMMENT '三方支付渠道编码',
		  country_code VARCHAR(16) NOT NULL COMMENT 'MiFaPay countryCode，GLOBAL 表示全球方式',
		  country_name VARCHAR(64) NOT NULL DEFAULT '' COMMENT '国家/地区名称',
		  currency_code VARCHAR(8) NOT NULL COMMENT '下单币种',
		  pay_way VARCHAR(64) NOT NULL COMMENT 'MiFaPay payWay',
		  pay_type VARCHAR(64) NOT NULL COMMENT 'MiFaPay payType',
		  method_name VARCHAR(128) NOT NULL COMMENT '支付方式展示名',
		  logo_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '支付方式 logo',
		  status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '状态：active/disabled',
		  usd_to_currency_rate DECIMAL(24,8) NOT NULL DEFAULT 0 COMMENT '1 USD 可兑换本币金额；0 表示未配置，不在 H5 展示',
		  sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重',
		  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
		  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
		  PRIMARY KEY (method_id),
		  UNIQUE KEY uk_third_party_payment_method (app_code, provider_code, country_code, pay_way, pay_type),
		  KEY idx_third_party_payment_methods_country (app_code, provider_code, country_code, status, sort_order)
		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='三方支付国家和方式配置表'`); err != nil {
		return err
	}
	if _, err := db.ExecContext(ctx, `
		CREATE TABLE IF NOT EXISTS external_recharge_orders (
		  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
		  order_id VARCHAR(96) NOT NULL COMMENT '平台外部充值订单 ID',
		  command_id VARCHAR(128) NOT NULL COMMENT '客户端命令幂等 ID',
		  target_user_id BIGINT NOT NULL COMMENT '充值目标用户 ID',
		  target_region_id BIGINT NOT NULL COMMENT '充值目标区域 ID',
		  target_country_id BIGINT NOT NULL DEFAULT 0 COMMENT '充值目标国家 ID',
		  target_country_code VARCHAR(16) NOT NULL DEFAULT '' COMMENT '充值目标国家码',
		  audience_type VARCHAR(32) NOT NULL DEFAULT 'normal' COMMENT '商品适用用户类型',
		  product_id BIGINT NOT NULL COMMENT '充值商品 ID',
		  product_code VARCHAR(128) NOT NULL DEFAULT '' COMMENT '充值商品编码快照',
		  product_name VARCHAR(128) NOT NULL DEFAULT '' COMMENT '充值商品名称快照',
		  coin_amount BIGINT NOT NULL COMMENT '到账金币数量',
		  usd_minor_amount BIGINT NOT NULL COMMENT '美元最小单位金额',
		  provider_code VARCHAR(32) NOT NULL COMMENT '支付渠道：mifapay/usdt_trc20',
		  payment_method_id BIGINT NOT NULL DEFAULT 0 COMMENT '三方支付方式 ID',
		  country_code VARCHAR(16) NOT NULL DEFAULT '' COMMENT '支付国家码',
		  currency_code VARCHAR(8) NOT NULL DEFAULT '' COMMENT '支付币种',
		  provider_amount_minor BIGINT NOT NULL DEFAULT 0 COMMENT '三方下单金额最小单位',
		  pay_way VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'MiFaPay payWay',
		  pay_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'MiFaPay payType',
		  pay_url TEXT NULL COMMENT '三方收银台地址',
		  provider_order_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '三方订单号',
		  tx_hash VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'USDT-TRC20 交易哈希',
		  receive_address VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'USDT 收款地址',
		  status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT 'pending/redirected/credited/failed',
		  failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因',
		  wallet_transaction_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '入账钱包交易 ID',
		  provider_payload JSON NULL COMMENT '三方原始响应或链上交易快照',
		  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
		  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
		  PRIMARY KEY (app_code, order_id),
		  UNIQUE KEY uk_external_recharge_command (app_code, command_id),
		  KEY idx_external_recharge_user_time (app_code, target_user_id, created_at_ms),
		  KEY idx_external_recharge_provider_order (app_code, provider_code, provider_order_id),
		  KEY idx_external_recharge_reconcile (app_code, status, provider_code, updated_at_ms, created_at_ms),
		  KEY idx_external_recharge_tx (app_code, provider_code, tx_hash)
		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='H5 外部充值订单表'`); err != nil {
		return err
	}
	if _, err := db.ExecContext(ctx, `
		ALTER TABLE external_recharge_orders
		ADD COLUMN target_country_id BIGINT NOT NULL DEFAULT 0 COMMENT '充值目标国家 ID' AFTER target_region_id`); err != nil && !isDuplicateColumnError(err) {
		return err
	}
	return seedThirdPartyPaymentDefaults(ctx, db)
}

func ensureGiftDiamondRatioSchema(ctx context.Context, db *sql.DB) error {
	if _, err := db.ExecContext(ctx, `
		CREATE TABLE IF NOT EXISTS gift_diamond_ratio_configs (
		  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
		  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '房间可见区域，0 表示全局默认',
		  gift_type_code VARCHAR(32) NOT NULL COMMENT '礼物类型编码',
		  status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '业务状态',
		  ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 100.00 COMMENT '房间贡献热度和主播周期钻石入账比例，百分比',
		  coin_return_ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 0.00 COMMENT '收礼人金币返还比例，百分比',
		  created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建后台用户 ID',
		  updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新后台用户 ID',
		  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
		  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
		  PRIMARY KEY (app_code, region_id, gift_type_code),
		  KEY idx_gift_diamond_ratio_region (app_code, region_id, status)
		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='礼物钻石和房间贡献比例配置表'`); err != nil {
		return err
	}
	if added, err := ensureGiftReturnCoinRatioColumn(ctx, db); err != nil {
		return err
	} else if added {

		if err := seedGiftReturnCoinRatioDefaults(ctx, db); err != nil {
			return err
		}
	}
	_, err := db.ExecContext(ctx, `
		INSERT IGNORE INTO gift_diamond_ratio_configs (
		  app_code, region_id, gift_type_code, status, ratio_percent, coin_return_ratio_percent,
		  created_by_admin_id, updated_by_admin_id, created_at_ms, updated_at_ms
		) VALUES
		  ('lalu', 0, 'normal', 'active', 100.00, 30.00, 0, 0, 0, 0),
		  ('lalu', 0, 'lucky', 'active', 10.00, 10.00, 0, 0, 0, 0),
		  ('lalu', 0, 'super_lucky', 'active', 1.00, 1.00, 0, 0, 0, 0)`)
	return err
}

func ensureGiftReturnCoinRatioColumn(ctx context.Context, db *sql.DB) (bool, error) {

	if _, err := db.ExecContext(ctx, `
		ALTER TABLE gift_diamond_ratio_configs
		ADD COLUMN coin_return_ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 0.00 COMMENT '收礼人金币返还比例，百分比' AFTER ratio_percent`); err != nil {
		if isDuplicateColumnError(err) {
			return false, nil
		}
		return false, err
	}
	return true, nil
}

func seedGiftReturnCoinRatioDefaults(ctx context.Context, db *sql.DB) error {

	_, err := db.ExecContext(ctx, `
		UPDATE gift_diamond_ratio_configs
		SET coin_return_ratio_percent = CASE gift_type_code
		  WHEN 'lucky' THEN 10.00
		  WHEN 'super_lucky' THEN 1.00
		  ELSE 30.00
		END`)
	return err
}

func ensureCoinSellerSalaryExchangeRateSchema(ctx context.Context, db *sql.DB) error {
	_, err := db.ExecContext(ctx, `
		CREATE TABLE IF NOT EXISTS coin_seller_salary_exchange_rate_tiers (
		  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
		  region_id BIGINT NOT NULL COMMENT '币商所属区域 ID',
		  tier_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '区间 ID',
		  min_usd_minor BIGINT NOT NULL COMMENT '起始美元金额，单位美分，包含',
		  max_usd_minor BIGINT NOT NULL COMMENT '结束美元金额，单位美分，包含',
		  coin_per_usd BIGINT NOT NULL COMMENT '每 1 USD 工资可兑换的币商专用金币数量',
		  status VARCHAR(24) NOT NULL DEFAULT 'active' COMMENT '状态：active/disabled',
		  sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重',
		  created_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建人用户 ID',
		  updated_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新人用户 ID',
		  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
		  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
		  PRIMARY KEY (tier_id),
		  KEY idx_coin_seller_salary_rates_region (app_code, region_id, status, min_usd_minor, max_usd_minor),
		  KEY idx_coin_seller_salary_rates_sort (app_code, region_id, status, sort_order)
		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='币商工资兑换比例区间表'`)
	return err
}

func ensureUserResourceEquipmentSchema(ctx context.Context, db *sql.DB) error {

	if _, err := db.ExecContext(ctx, `
		CREATE TABLE IF NOT EXISTS user_resource_equipment (
		  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
		  user_id BIGINT NOT NULL COMMENT '用户 ID',
		  resource_type VARCHAR(32) NOT NULL COMMENT '资源类型',
		  entitlement_id VARCHAR(96) NOT NULL COMMENT '权益 ID',
		  resource_id BIGINT NOT NULL COMMENT '资源 ID',
		  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
		  PRIMARY KEY (app_code, user_id, resource_type, entitlement_id),
		  KEY idx_user_resource_equipment_user (app_code, user_id, updated_at_ms)
		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户资源装备表'`); err != nil {
		return err
	}

	primaryColumns, err := tablePrimaryKeyColumns(ctx, db, "user_resource_equipment")
	if err != nil {
		return err
	}
	if strings.Join(primaryColumns, ",") == "app_code,user_id,resource_type" {
		_, err = db.ExecContext(ctx, `
			ALTER TABLE user_resource_equipment
			DROP PRIMARY KEY,
			ADD PRIMARY KEY (app_code, user_id, resource_type, entitlement_id)`)
		return err
	}
	return nil
}

func tablePrimaryKeyColumns(ctx context.Context, db *sql.DB, tableName string) ([]string, error) {
	rows, err := db.QueryContext(ctx, `
		SELECT COLUMN_NAME
		FROM information_schema.KEY_COLUMN_USAGE
		WHERE TABLE_SCHEMA = DATABASE()
		  AND TABLE_NAME = ?
		  AND CONSTRAINT_NAME = 'PRIMARY'
		ORDER BY ORDINAL_POSITION ASC`, tableName)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	columns := make([]string, 0, 4)
	for rows.Next() {
		var column string
		if err := rows.Scan(&column); err != nil {
			return nil, err
		}
		columns = append(columns, column)
	}
	return columns, rows.Err()
}
