package mysql

import "context"

func (r *Repository) ensureAgencyOpeningTables(ctx context.Context) error {
	statements := []string{
		`CREATE TABLE IF NOT EXISTS agency_opening_cycles (
		  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
		  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '配置区域 ID；0 表示全区域默认活动',
		  cycle_id VARCHAR(96) NOT NULL COMMENT '代理开业周期 ID',
		  activity_code VARCHAR(64) NOT NULL DEFAULT 'agency_opening' COMMENT '活动编码',
		  title VARCHAR(128) NOT NULL DEFAULT '' COMMENT '周期标题',
		  status VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT 'draft/active/disabled/settling/settled',
		  start_ms BIGINT NOT NULL COMMENT 'UTC epoch ms 开始，包含',
		  end_ms BIGINT NOT NULL COMMENT 'UTC epoch ms 结束，不包含',
		  min_host_count INT NOT NULL DEFAULT 10 COMMENT '申请要求的有效主播数',
		  max_agency_age_days INT NOT NULL DEFAULT 7 COMMENT '代理创建后允许申请的最大天数，0 表示不限制',
		  created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建管理员',
		  updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新管理员',
		  settled_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '结算完成时间',
		  locked_by VARCHAR(96) NOT NULL DEFAULT '' COMMENT '结算 worker 锁',
		  lock_until_ms BIGINT 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, cycle_id),
		  KEY idx_agency_opening_cycle_current (app_code, region_id, activity_code, status, start_ms, end_ms),
		  KEY idx_agency_opening_cycle_due (app_code, activity_code, status, end_ms, lock_until_ms)
		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='代理开业活动周期'`,
		`CREATE TABLE IF NOT EXISTS agency_opening_cycle_rewards (
			  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
			  cycle_id VARCHAR(96) NOT NULL COMMENT '代理开业周期 ID',
			  rank_no INT NOT NULL COMMENT '档位序号',
			  threshold_coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '命中该档需要的代理房间贡献值 HeatValue',
			  reward_coin_amount BIGINT 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, cycle_id, rank_no)
			) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='代理开业流水奖励档位'`,
		`CREATE TABLE IF NOT EXISTS agency_opening_applications (
		  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
		  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '申请时代理实际区域 ID',
		  application_id VARCHAR(96) NOT NULL COMMENT '申请 ID',
		  cycle_id VARCHAR(96) NOT NULL COMMENT '代理开业周期 ID',
		  agency_id BIGINT NOT NULL COMMENT '代理 ID',
		  agency_owner_user_id BIGINT NOT NULL COMMENT '代理 owner 用户 ID',
		  agency_name VARCHAR(128) NOT NULL DEFAULT '' COMMENT '代理名称快照',
		  host_count INT NOT NULL DEFAULT 0 COMMENT '申请时有效主播数快照',
		  agency_created_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '代理创建时间快照',
			  status VARCHAR(32) NOT NULL DEFAULT 'applied' COMMENT 'applied/approved/pending/granted/failed/expired',
			  score_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '历史字段名：周期内开业房间贡献值 HeatValue',
			  reward_rank_no INT NOT NULL DEFAULT 0 COMMENT '结算命中的档位序号',
			  reward_threshold_coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '结算命中的流水阈值',
			  reward_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '结算奖励金币',
		  wallet_command_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '钱包幂等命令',
		  wallet_transaction_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '钱包交易 ID',
		  failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因',
		  applied_at_ms BIGINT NOT NULL COMMENT '申请时间',
		  approved_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '后台同意时间',
		  score_start_ms BIGINT NOT NULL DEFAULT 0 COMMENT '计分开始时间',
		  score_end_ms BIGINT NOT NULL DEFAULT 0 COMMENT '计分截止时间',
		  reviewed_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '审核管理员',
		  granted_at_ms BIGINT 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, application_id),
		  UNIQUE KEY uk_agency_opening_owner_once (app_code, agency_owner_user_id),
		  KEY idx_agency_opening_wallet_command (app_code, wallet_command_id),
		  KEY idx_agency_opening_application_owner (app_code, agency_owner_user_id, applied_at_ms),
		  KEY idx_agency_opening_agency_cycle (app_code, cycle_id, agency_id),
		  KEY idx_agency_opening_application_rank (app_code, cycle_id, score_coin_amount, applied_at_ms, agency_id),
		  KEY idx_agency_opening_application_status (app_code, cycle_id, status, updated_at_ms),
		  KEY idx_agency_opening_application_region (app_code, region_id, updated_at_ms, application_id)
		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='代理开业申请和结算事实'`,
		`CREATE TABLE IF NOT EXISTS agency_opening_score_events (
		  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
		  source_event_id VARCHAR(128) NOT NULL COMMENT 'room-service outbox event_id',
		  cycle_id VARCHAR(96) NOT NULL COMMENT '代理开业周期 ID',
		  application_id VARCHAR(96) NOT NULL COMMENT '命中的申请 ID',
		  agency_id BIGINT NOT NULL COMMENT '代理 ID',
		  target_user_id BIGINT NOT NULL COMMENT '收礼主播用户 ID',
		  score_delta BIGINT NOT NULL COMMENT '本次房间贡献值 HeatValue',
		  occurred_at_ms BIGINT NOT NULL COMMENT '事件发生时间，UTC epoch ms',
		  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
		  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '事件发生时房间区域 ID',
		  PRIMARY KEY (app_code, source_event_id),
		  KEY idx_agency_opening_score_event_application (app_code, application_id, occurred_at_ms)
		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='代理开业流水事件幂等表'`,
	}
	for _, statement := range statements {
		if _, err := r.db.ExecContext(ctx, statement); err != nil {
			return err
		}
	}
	if err := r.ensureAgencyOpeningRegionSchema(ctx); err != nil {
		return err
	}
	if err := r.ensureAgencyOpeningRewardTierColumns(ctx); err != nil {
		return err
	}
	return r.ensureAgencyOpeningApplicationOwnerOnceIndex(ctx)
}

func (r *Repository) ensureAgencyOpeningRegionSchema(ctx context.Context) error {
	// 历史活动回填为 0 后继续作为全区域默认活动；申请和积分事件仍固化代理的实际区域。
	additions := []struct {
		table     string
		statement string
	}{
		{"agency_opening_cycles", `ALTER TABLE agency_opening_cycles ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 COMMENT '配置区域 ID；0 表示全区域默认活动', ALGORITHM=INSTANT`},
		{"agency_opening_applications", `ALTER TABLE agency_opening_applications ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 COMMENT '申请时代理实际区域 ID', ALGORITHM=INSTANT`},
		{"agency_opening_score_events", `ALTER TABLE agency_opening_score_events ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 COMMENT '事件发生时房间区域 ID', ALGORITHM=INSTANT`},
	}
	for _, addition := range additions {
		exists, err := r.columnExists(ctx, addition.table, "region_id")
		if err != nil {
			return err
		}
		if !exists {
			if _, err := r.db.ExecContext(ctx, addition.statement); err != nil {
				return err
			}
		}
	}
	currentIndex := []string{"app_code", "region_id", "activity_code", "status", "start_ms", "end_ms"}
	if matches, err := r.indexColumnsMatch(ctx, "agency_opening_cycles", "idx_agency_opening_cycle_current", currentIndex); err != nil {
		return err
	} else if !matches {
		if _, err := r.db.ExecContext(ctx, `ALTER TABLE agency_opening_cycles DROP INDEX idx_agency_opening_cycle_current, ADD KEY idx_agency_opening_cycle_current (app_code, region_id, activity_code, status, start_ms, end_ms), ALGORITHM=INPLACE, LOCK=NONE`); err != nil {
			return err
		}
	}
	regionIndexExists, err := r.indexExists(ctx, "agency_opening_applications", "idx_agency_opening_application_region")
	if err != nil {
		return err
	}
	if !regionIndexExists {
		if _, err := r.db.ExecContext(ctx, `ALTER TABLE agency_opening_applications ADD KEY idx_agency_opening_application_region (app_code, region_id, updated_at_ms, application_id), ALGORITHM=INPLACE, LOCK=NONE`); err != nil {
			return err
		}
	}
	return nil
}

func (r *Repository) ensureAgencyOpeningRewardTierColumns(ctx context.Context) error {
	if exists, err := r.columnExists(ctx, "agency_opening_cycle_rewards", "threshold_coin_spent"); err != nil {
		return err
	} else if !exists {
		// 旧本地表按 Top 名次发奖；新增阈值列后，rank_no 只作为档位序号保留，实际结算按 threshold_coin_spent 命中。
		if _, err := r.db.ExecContext(ctx, `ALTER TABLE agency_opening_cycle_rewards ADD COLUMN threshold_coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '命中该档需要的代理房间流水金币' AFTER rank_no`); err != nil {
			return err
		}
	}
	if exists, err := r.columnExists(ctx, "agency_opening_applications", "reward_threshold_coin_spent"); err != nil {
		return err
	} else if !exists {
		if _, err := r.db.ExecContext(ctx, `ALTER TABLE agency_opening_applications ADD COLUMN reward_threshold_coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '结算命中的流水阈值' AFTER reward_rank_no`); err != nil {
			return err
		}
	}
	if exists, err := r.columnExists(ctx, "agency_opening_applications", "approved_at_ms"); err != nil {
		return err
	} else if !exists {
		if _, err := r.db.ExecContext(ctx, `ALTER TABLE agency_opening_applications ADD COLUMN approved_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '后台同意时间' AFTER applied_at_ms`); err != nil {
			return err
		}
	}
	if exists, err := r.columnExists(ctx, "agency_opening_applications", "score_start_ms"); err != nil {
		return err
	} else if !exists {
		if _, err := r.db.ExecContext(ctx, `ALTER TABLE agency_opening_applications ADD COLUMN score_start_ms BIGINT NOT NULL DEFAULT 0 COMMENT '计分开始时间' AFTER approved_at_ms`); err != nil {
			return err
		}
	}
	if exists, err := r.columnExists(ctx, "agency_opening_applications", "score_end_ms"); err != nil {
		return err
	} else if !exists {
		if _, err := r.db.ExecContext(ctx, `ALTER TABLE agency_opening_applications ADD COLUMN score_end_ms BIGINT NOT NULL DEFAULT 0 COMMENT '计分截止时间' AFTER score_start_ms`); err != nil {
			return err
		}
	}
	if exists, err := r.columnExists(ctx, "agency_opening_applications", "reviewed_by_admin_id"); err != nil {
		return err
	} else if !exists {
		if _, err := r.db.ExecContext(ctx, `ALTER TABLE agency_opening_applications ADD COLUMN reviewed_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '审核管理员' AFTER score_end_ms`); err != nil {
			return err
		}
	}
	return nil
}

func (r *Repository) ensureAgencyOpeningApplicationOwnerOnceIndex(ctx context.Context) error {
	ownerOnceExists, err := r.indexExists(ctx, "agency_opening_applications", "uk_agency_opening_owner_once")
	if err != nil {
		return err
	}
	if !ownerOnceExists {
		// 申请资格是用户维度的一次性活动，唯一键先落在 owner_user_id 上，避免新周期或更换 agency 后重复参与。
		if _, err := r.db.ExecContext(ctx, `ALTER TABLE agency_opening_applications ADD UNIQUE KEY uk_agency_opening_owner_once (app_code, agency_owner_user_id)`); err != nil {
			return err
		}
	}
	oldAgencyCycleUniqueExists, err := r.indexExists(ctx, "agency_opening_applications", "uk_agency_opening_agency_cycle")
	if err != nil {
		return err
	}
	if oldAgencyCycleUniqueExists {
		// 旧唯一键只限制同一周期同一 agency，不能表达“每个用户只能参与一次”，降级成普通查询索引即可。
		if _, err := r.db.ExecContext(ctx, `ALTER TABLE agency_opening_applications DROP INDEX uk_agency_opening_agency_cycle`); err != nil {
			return err
		}
	}
	agencyCycleIndexExists, err := r.indexExists(ctx, "agency_opening_applications", "idx_agency_opening_agency_cycle")
	if err != nil {
		return err
	}
	if !agencyCycleIndexExists {
		if _, err := r.db.ExecContext(ctx, `ALTER TABLE agency_opening_applications ADD KEY idx_agency_opening_agency_cycle (app_code, cycle_id, agency_id)`); err != nil {
			return err
		}
	}
	return nil
}
