USE youlai_admin;

-- 齐云 IP 上游适配升级脚本

SET @schema_name = DATABASE();

-- 兼容未执行会员代理归属升级脚本的数据库。
-- 当前 StaticProxyAsset 实体已包含 memberUserId，MyBatis-Plus 查询会选择 member_user_id；
-- 老库缺少该字段时，静态代理自动续费/同步定时任务会报 Unknown column。
SET @column_exists = (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_static_proxy_asset'
    AND COLUMN_NAME = 'member_user_id'
);
SET @sql = IF(
  @column_exists = 0,
  'ALTER TABLE `xxk_static_proxy_asset` ADD COLUMN `member_user_id` BIGINT NULL COMMENT ''会员ID'' AFTER `user_id`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_static_proxy_asset'
    AND INDEX_NAME = 'idx_xxk_static_proxy_asset_member_user_id'
);
SET @sql = IF(
  @index_exists = 0,
  'ALTER TABLE `xxk_static_proxy_asset` ADD INDEX `idx_xxk_static_proxy_asset_member_user_id` (`member_user_id`) USING BTREE',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

-- 会员侧订单开通会写入 member_user_id；这些表如果仍是旧结构，会导致上游已开通但本地资源/白名单插入失败。
ALTER TABLE `xxk_dynamic_channel` MODIFY COLUMN `user_id` BIGINT NULL COMMENT '用户ID';

SET @column_exists = (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_dynamic_channel'
    AND COLUMN_NAME = 'member_user_id'
);
SET @sql = IF(
  @column_exists = 0,
  'ALTER TABLE `xxk_dynamic_channel` ADD COLUMN `member_user_id` BIGINT NULL COMMENT ''会员ID'' AFTER `user_id`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_dynamic_channel'
    AND INDEX_NAME = 'idx_xxk_dynamic_channel_member_user_id'
);
SET @sql = IF(
  @index_exists = 0,
  'ALTER TABLE `xxk_dynamic_channel` ADD INDEX `idx_xxk_dynamic_channel_member_user_id` (`member_user_id`) USING BTREE',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

ALTER TABLE `xxk_dynamic_channel_traffic_log` MODIFY COLUMN `user_id` BIGINT NULL COMMENT '用户ID';

SET @column_exists = (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_dynamic_channel_traffic_log'
    AND COLUMN_NAME = 'member_user_id'
);
SET @sql = IF(
  @column_exists = 0,
  'ALTER TABLE `xxk_dynamic_channel_traffic_log` ADD COLUMN `member_user_id` BIGINT NULL COMMENT ''会员ID'' AFTER `user_id`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_dynamic_channel_traffic_log'
    AND INDEX_NAME = 'idx_xxk_dynamic_channel_traffic_log_member_user_id'
);
SET @sql = IF(
  @index_exists = 0,
  'ALTER TABLE `xxk_dynamic_channel_traffic_log` ADD INDEX `idx_xxk_dynamic_channel_traffic_log_member_user_id` (`member_user_id`) USING BTREE',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

ALTER TABLE `xxk_dynamic_proxy_generate_log` MODIFY COLUMN `user_id` BIGINT NULL COMMENT '用户ID';

SET @column_exists = (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_dynamic_proxy_generate_log'
    AND COLUMN_NAME = 'member_user_id'
);
SET @sql = IF(
  @column_exists = 0,
  'ALTER TABLE `xxk_dynamic_proxy_generate_log` ADD COLUMN `member_user_id` BIGINT NULL COMMENT ''会员ID'' AFTER `user_id`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_dynamic_proxy_generate_log'
    AND INDEX_NAME = 'idx_xxk_dynamic_proxy_generate_log_member_user_id'
);
SET @sql = IF(
  @index_exists = 0,
  'ALTER TABLE `xxk_dynamic_proxy_generate_log` ADD INDEX `idx_xxk_dynamic_proxy_generate_log_member_user_id` (`member_user_id`) USING BTREE',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

ALTER TABLE `xxk_static_proxy_asset` MODIFY COLUMN `user_id` BIGINT NULL COMMENT '用户ID';
ALTER TABLE `xxk_static_proxy_whitelist` MODIFY COLUMN `user_id` BIGINT NULL COMMENT '用户ID';

SET @column_exists = (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_static_proxy_whitelist'
    AND COLUMN_NAME = 'member_user_id'
);
SET @sql = IF(
  @column_exists = 0,
  'ALTER TABLE `xxk_static_proxy_whitelist` ADD COLUMN `member_user_id` BIGINT NULL COMMENT ''会员ID'' AFTER `user_id`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_static_proxy_whitelist'
    AND INDEX_NAME = 'uk_member_whitelist_ip'
);
SET @sql = IF(
  @index_exists = 0,
  'ALTER TABLE `xxk_static_proxy_whitelist` ADD UNIQUE KEY `uk_member_whitelist_ip` (`member_user_id`, `whitelist_ip`) USING BTREE',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_static_proxy_whitelist'
    AND INDEX_NAME = 'idx_xxk_static_proxy_whitelist_member_user_id'
);
SET @sql = IF(
  @index_exists = 0,
  'ALTER TABLE `xxk_static_proxy_whitelist` ADD INDEX `idx_xxk_static_proxy_whitelist_member_user_id` (`member_user_id`) USING BTREE',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @column_exists = (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_product'
    AND COLUMN_NAME = 'upstream_params'
);
SET @sql = IF(
  @column_exists = 0,
  'ALTER TABLE `xxk_product` ADD COLUMN `upstream_params` text DEFAULT NULL COMMENT ''上游扩展参数JSON'' AFTER `purpose_web`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @column_exists = (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_product'
    AND COLUMN_NAME = 'upstream_capabilities'
);
SET @sql = IF(
  @column_exists = 0,
  'ALTER TABLE `xxk_product` ADD COLUMN `upstream_capabilities` text DEFAULT NULL COMMENT ''上游能力JSON'' AFTER `upstream_params`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @column_exists = (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_product_duration_multiplier'
    AND COLUMN_NAME = 'duration_unit'
);
SET @sql = IF(
  @column_exists = 0,
  'ALTER TABLE `xxk_product_duration_multiplier` ADD COLUMN `duration_unit` varchar(16) NOT NULL DEFAULT ''DAY'' COMMENT ''时长单位(DAY天/HOUR小时)'' AFTER `duration_days`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @column_exists = (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_product_duration_multiplier'
    AND COLUMN_NAME = 'duration_value'
);
SET @sql = IF(
  @column_exists = 0,
  'ALTER TABLE `xxk_product_duration_multiplier` ADD COLUMN `duration_value` int NOT NULL DEFAULT 1 COMMENT ''时长数值'' AFTER `duration_unit`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

UPDATE `xxk_product_duration_multiplier`
SET `duration_unit` = 'DAY',
    `duration_value` = `duration_days`
WHERE (`duration_unit` IS NULL OR `duration_unit` = '' OR `duration_unit` = 'DAY')
  AND (`duration_value` IS NULL OR `duration_value` <= 1);

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_product_duration_multiplier'
    AND INDEX_NAME = 'uk_product_duration'
);
SET @sql = IF(
  @index_exists > 0,
  'ALTER TABLE `xxk_product_duration_multiplier` DROP INDEX `uk_product_duration`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_product_duration_multiplier'
    AND INDEX_NAME = 'uk_product_duration_unit_value'
);
SET @sql = IF(
  @index_exists = 0,
  'ALTER TABLE `xxk_product_duration_multiplier` ADD UNIQUE KEY `uk_product_duration_unit_value` (`product_id`, `duration_unit`, `duration_value`) USING BTREE',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_product_duration_multiplier'
    AND INDEX_NAME = 'idx_product_duration_days'
);
SET @sql = IF(
  @index_exists = 0,
  'ALTER TABLE `xxk_product_duration_multiplier` ADD INDEX `idx_product_duration_days` (`product_id`, `duration_days`) USING BTREE',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @column_exists = (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'xxk_product_static_country_price' AND COLUMN_NAME = 'price_type');
SET @sql = IF(@column_exists = 0, 'ALTER TABLE `xxk_product_static_country_price` ADD COLUMN `price_type` varchar(20) DEFAULT NULL COMMENT ''价格类型(DEFAULT默认/NODE特殊节点)'' AFTER `product_id`', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @column_exists = (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'xxk_product_static_country_price' AND COLUMN_NAME = 'qiyun_product_type');
SET @sql = IF(@column_exists = 0, 'ALTER TABLE `xxk_product_static_country_price` ADD COLUMN `qiyun_product_type` varchar(32) DEFAULT NULL COMMENT ''齐云产品类型'' AFTER `price_type`', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @column_exists = (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'xxk_product_static_country_price' AND COLUMN_NAME = 'qiyun_pid');
SET @sql = IF(@column_exists = 0, 'ALTER TABLE `xxk_product_static_country_price` ADD COLUMN `qiyun_pid` varchar(64) DEFAULT NULL COMMENT ''齐云项目ID'' AFTER `qiyun_product_type`', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @column_exists = (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'xxk_product_static_country_price' AND COLUMN_NAME = 'qiyun_project_name');
SET @sql = IF(@column_exists = 0, 'ALTER TABLE `xxk_product_static_country_price` ADD COLUMN `qiyun_project_name` varchar(255) DEFAULT NULL COMMENT ''齐云项目名称'' AFTER `qiyun_pid`', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @column_exists = (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'xxk_product_static_country_price' AND COLUMN_NAME = 'qiyun_area_id');
SET @sql = IF(@column_exists = 0, 'ALTER TABLE `xxk_product_static_country_price` ADD COLUMN `qiyun_area_id` varchar(64) DEFAULT NULL COMMENT ''齐云省份ID'' AFTER `qiyun_project_name`', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @column_exists = (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'xxk_product_static_country_price' AND COLUMN_NAME = 'qiyun_area_name');
SET @sql = IF(@column_exists = 0, 'ALTER TABLE `xxk_product_static_country_price` ADD COLUMN `qiyun_area_name` varchar(255) DEFAULT NULL COMMENT ''齐云省份名称'' AFTER `qiyun_area_id`', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @column_exists = (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'xxk_product_static_country_price' AND COLUMN_NAME = 'qiyun_node_id');
SET @sql = IF(@column_exists = 0, 'ALTER TABLE `xxk_product_static_country_price` ADD COLUMN `qiyun_node_id` varchar(100) DEFAULT NULL COMMENT ''齐云节点ID'' AFTER `qiyun_area_name`', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @column_exists = (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'xxk_product_static_country_price' AND COLUMN_NAME = 'qiyun_node_name');
SET @sql = IF(@column_exists = 0, 'ALTER TABLE `xxk_product_static_country_price` ADD COLUMN `qiyun_node_name` varchar(255) DEFAULT NULL COMMENT ''齐云节点名称'' AFTER `qiyun_node_id`', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

ALTER TABLE `xxk_product` MODIFY COLUMN `currency` varchar(10) DEFAULT 'RMB' COMMENT '币种';
ALTER TABLE `xxk_product_static_country_price` MODIFY COLUMN `currency` varchar(10) DEFAULT 'RMB' COMMENT '币种';
ALTER TABLE `xxk_proxy_order` MODIFY COLUMN `currency` varchar(10) DEFAULT 'RMB' COMMENT '币种';

UPDATE `xxk_product` SET `currency` = 'RMB' WHERE `currency` IS NULL OR `currency` = '' OR `currency` = 'USD';
UPDATE `xxk_product_static_country_price` SET `currency` = 'RMB' WHERE `currency` IS NULL OR `currency` = '' OR `currency` = 'USD';
UPDATE `xxk_proxy_order` SET `currency` = 'RMB' WHERE `currency` IS NULL OR `currency` = '' OR `currency` = 'USD';

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_product_static_country_price'
    AND INDEX_NAME = 'uk_product_country'
);
SET @sql = IF(
  @index_exists > 0,
  'ALTER TABLE `xxk_product_static_country_price` DROP INDEX `uk_product_country`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_product_static_country_price'
    AND INDEX_NAME = 'idx_product_country'
);
SET @sql = IF(
  @index_exists = 0,
  'ALTER TABLE `xxk_product_static_country_price` ADD INDEX `idx_product_country` (`product_id`, `country_code`) USING BTREE',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @index_exists = (
  SELECT COUNT(1)
  FROM information_schema.STATISTICS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_product_static_country_price'
    AND INDEX_NAME = 'idx_static_price_qiyun_node'
);
SET @sql = IF(
  @index_exists = 0,
  'ALTER TABLE `xxk_product_static_country_price` ADD INDEX `idx_static_price_qiyun_node` (`product_id`, `price_type`, `qiyun_node_id`) USING BTREE',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

UPDATE `xxk_upstream_provider`
SET `provider_code` = 'QIYUN01',
    `provider_name` = '齐云IP',
    `provider_type` = 'QIYUN',
    `base_url` = 'https://www.qiyunip.com',
    `auth_user_id` = NULL,
    `auth_token` = NULL,
    `success_codes` = '1'
WHERE `provider_type` = 'IPNUX';

-- 开放 API 模块补丁：应用、申请、独立账户、充值、回调日志和后台菜单。
CREATE TABLE IF NOT EXISTS `xxk_open_api_app` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `app_id` VARCHAR(64) NOT NULL COMMENT '应用ID',
  `app_name` VARCHAR(128) NOT NULL COMMENT '应用名称',
  `app_secret` VARCHAR(128) NOT NULL COMMENT '应用密钥',
  `member_user_id` BIGINT NOT NULL COMMENT '绑定会员ID',
  `status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态(0停用 1启用)',
  `allow_ip_list` TEXT DEFAULT NULL COMMENT '允许访问IP列表，逗号/换行分隔',
  `callback_url` VARCHAR(255) DEFAULT NULL COMMENT '订单结果回调地址',
  `callback_secret` VARCHAR(128) DEFAULT NULL COMMENT '订单结果回调签名密钥',
  `last_auth_time` DATETIME DEFAULT NULL COMMENT '最近换取token时间',
  `last_auth_ip` VARCHAR(64) DEFAULT NULL COMMENT '最近换取token IP',
  `remark` VARCHAR(255) DEFAULT NULL COMMENT '备注',
  `create_by` BIGINT DEFAULT NULL COMMENT '创建人ID',
  `update_by` BIGINT DEFAULT NULL COMMENT '更新人ID',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `is_deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除(0否 1是)',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_xxk_open_api_app_app_id` (`app_id`),
  UNIQUE KEY `uk_xxk_open_api_app_member_user_id` (`member_user_id`),
  KEY `idx_xxk_open_api_app_member_user_id` (`member_user_id`),
  KEY `idx_xxk_open_api_app_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开放接口应用表';

SET @column_exists = (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_open_api_app'
    AND COLUMN_NAME = 'callback_url'
);
SET @sql = IF(
  @column_exists = 0,
  'ALTER TABLE `xxk_open_api_app` ADD COLUMN `callback_url` VARCHAR(255) DEFAULT NULL COMMENT ''订单结果回调地址'' AFTER `allow_ip_list`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @column_exists = (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @schema_name
    AND TABLE_NAME = 'xxk_open_api_app'
    AND COLUMN_NAME = 'callback_secret'
);
SET @sql = IF(
  @column_exists = 0,
  'ALTER TABLE `xxk_open_api_app` ADD COLUMN `callback_secret` VARCHAR(128) DEFAULT NULL COMMENT ''订单结果回调签名密钥'' AFTER `callback_url`',
  'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

CREATE TABLE IF NOT EXISTS `xxk_open_api_apply` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `apply_no` VARCHAR(64) NOT NULL COMMENT '申请单号',
  `member_user_id` BIGINT NOT NULL COMMENT '会员ID',
  `username_snapshot` VARCHAR(64) DEFAULT NULL COMMENT '用户名快照',
  `mobile_snapshot` VARCHAR(32) DEFAULT NULL COMMENT '手机号快照',
  `contact_name` VARCHAR(64) NOT NULL COMMENT '联系人',
  `contact_mobile` VARCHAR(32) DEFAULT NULL COMMENT '联系电话',
  `contact_email` VARCHAR(128) DEFAULT NULL COMMENT '联系邮箱',
  `company_name` VARCHAR(128) DEFAULT NULL COMMENT '公司名称',
  `purpose` VARCHAR(255) NOT NULL COMMENT '申请用途',
  `scenario_description` TEXT NOT NULL COMMENT '使用场景说明',
  `allow_ip_list` TEXT DEFAULT NULL COMMENT 'IP白名单',
  `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态(0待审核 1已通过 2已驳回)',
  `submit_remark` VARCHAR(255) DEFAULT NULL COMMENT '补充说明',
  `submit_time` DATETIME DEFAULT NULL COMMENT '提交时间',
  `audit_time` DATETIME DEFAULT NULL COMMENT '审核时间',
  `audit_by` BIGINT DEFAULT NULL COMMENT '审核人ID',
  `audit_remark` VARCHAR(255) DEFAULT NULL COMMENT '审核备注',
  `open_api_app_id` BIGINT DEFAULT NULL COMMENT '关联开放应用ID',
  `create_by` BIGINT DEFAULT NULL COMMENT '创建人ID',
  `update_by` BIGINT DEFAULT NULL COMMENT '更新人ID',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `is_deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除(0否 1是)',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_xxk_open_api_apply_no` (`apply_no`),
  KEY `idx_xxk_open_api_apply_member_user_id` (`member_user_id`),
  KEY `idx_xxk_open_api_apply_status` (`status`),
  KEY `idx_xxk_open_api_apply_submit_time` (`submit_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开放接口申请表';

CREATE TABLE IF NOT EXISTS `xxk_open_api_account` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `open_api_app_id` BIGINT NOT NULL COMMENT '开放应用ID',
  `member_user_id` BIGINT NOT NULL COMMENT '会员ID',
  `balance` DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '余额',
  `frozen_balance` DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '冻结余额',
  `total_recharge_amount` DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '累计充值金额',
  `total_consume_amount` DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '累计消费金额',
  `total_refund_amount` DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '累计退款金额',
  `status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态(0停用 1正常)',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_xxk_open_api_account_app_id` (`open_api_app_id`),
  KEY `idx_xxk_open_api_account_member_user_id` (`member_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='API独立账户表';

CREATE TABLE IF NOT EXISTS `xxk_open_api_account_flow` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `flow_no` VARCHAR(64) NOT NULL COMMENT '流水号',
  `open_api_app_id` BIGINT NOT NULL COMMENT '开放应用ID',
  `member_user_id` BIGINT NOT NULL COMMENT '会员ID',
  `biz_type` VARCHAR(64) NOT NULL COMMENT '业务类型',
  `change_type` VARCHAR(16) NOT NULL COMMENT '变动类型(IN/OUT)',
  `change_amount` DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '变动金额',
  `before_balance` DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '变动前余额',
  `after_balance` DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '变动后余额',
  `related_order_no` VARCHAR(64) DEFAULT NULL COMMENT '关联单号',
  `remark` VARCHAR(255) DEFAULT NULL COMMENT '备注',
  `operate_by` BIGINT DEFAULT NULL COMMENT '操作人ID',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_xxk_open_api_account_flow_no` (`flow_no`),
  KEY `idx_xxk_open_api_account_flow_app_id` (`open_api_app_id`),
  KEY `idx_xxk_open_api_account_flow_related_order_no` (`related_order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='API独立账户流水表';

CREATE TABLE IF NOT EXISTS `xxk_open_api_recharge_order` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `recharge_no` VARCHAR(64) NOT NULL COMMENT '充值单号',
  `pay_order_no` VARCHAR(64) NOT NULL COMMENT '支付单号',
  `open_api_app_id` BIGINT NOT NULL COMMENT '开放应用ID',
  `member_user_id` BIGINT NOT NULL COMMENT '会员ID',
  `payment_type` VARCHAR(32) NOT NULL COMMENT '支付方式',
  `pay_status` VARCHAR(32) NOT NULL COMMENT '支付状态',
  `channel_order_no` VARCHAR(64) DEFAULT NULL COMMENT '渠道订单号',
  `channel_response` LONGTEXT DEFAULT NULL COMMENT '渠道响应',
  `client_type` VARCHAR(32) DEFAULT NULL COMMENT '客户端类型',
  `return_url` VARCHAR(500) DEFAULT NULL COMMENT '回跳地址',
  `amount` DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '充值金额',
  `gift_amount` DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '赠送金额',
  `credited_amount` DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '到账金额',
  `promotion_rule_snapshot` TEXT DEFAULT NULL COMMENT '活动规则快照',
  `currency` VARCHAR(16) DEFAULT 'USD' COMMENT '币种',
  `paid_time` DATETIME DEFAULT NULL COMMENT '支付完成时间',
  `remark` VARCHAR(255) DEFAULT NULL COMMENT '备注',
  `is_deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除(0否 1是)',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_xxk_open_api_recharge_no` (`recharge_no`),
  UNIQUE KEY `uk_xxk_open_api_pay_order_no` (`pay_order_no`),
  KEY `idx_xxk_open_api_recharge_order_app_id` (`open_api_app_id`),
  KEY `idx_xxk_open_api_recharge_order_member_user_id` (`member_user_id`),
  KEY `idx_xxk_open_api_recharge_order_pay_status` (`pay_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='API独立账户充值单表';

CREATE TABLE IF NOT EXISTS `xxk_open_api_callback_log` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `open_api_app_id` BIGINT NOT NULL COMMENT '开放应用ID',
  `member_user_id` BIGINT NOT NULL COMMENT '会员ID',
  `order_id` BIGINT NOT NULL COMMENT '订单ID',
  `order_no` VARCHAR(64) NOT NULL COMMENT '订单号',
  `callback_url` VARCHAR(255) DEFAULT NULL COMMENT '回调地址',
  `event_type` VARCHAR(64) NOT NULL COMMENT '事件类型',
  `request_body` LONGTEXT DEFAULT NULL COMMENT '请求报文',
  `response_body` LONGTEXT DEFAULT NULL COMMENT '响应报文',
  `response_status` INT DEFAULT NULL COMMENT '响应HTTP状态码',
  `delivery_status` VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '投递状态(PENDING/SUCCESS/FAIL/SKIPPED)',
  `error_message` VARCHAR(500) DEFAULT NULL COMMENT '错误信息',
  `attempt_no` INT NOT NULL DEFAULT 1 COMMENT '尝试次数',
  `trigger_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '触发时间',
  `finish_time` DATETIME DEFAULT NULL COMMENT '完成时间',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_xxk_open_api_callback_log_app_id` (`open_api_app_id`),
  KEY `idx_xxk_open_api_callback_log_order_no` (`order_no`),
  KEY `idx_xxk_open_api_callback_log_status` (`delivery_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开放API订单回调日志表';

INSERT INTO `sys_menu`
(`id`, `parent_id`, `tree_path`, `name`, `type`, `route_name`, `route_path`, `component`, `perm`,
 `always_show`, `keep_alive`, `visible`, `sort`, `icon`, `redirect`, `create_time`, `update_time`, `params`)
VALUES
(1220, 1100, '0,1100', '开放API管理', 'C', NULL, '/open-api-manage', 'Layout', NULL,
 1, 0, 1, 13, 'api', '/open-api-manage/open-api', NOW(), NOW(), NULL),
(1221, 1220, '0,1100,1220', '开放API申请审核', 'M', 'ProxyOpenApiApply', 'open-api', 'proxy/open-api/index', NULL,
 0, 1, 1, 1, 'form', NULL, NOW(), NOW(), NULL),
(122101, 1221, '0,1100,1220,1221', '开放API申请查询', 'B', NULL, '', NULL, 'openapi:apply:list',
 NULL, NULL, 1, 1, '', NULL, NOW(), NOW(), NULL),
(122102, 1221, '0,1100,1220,1221', '开放API申请审核', 'B', NULL, '', NULL, 'openapi:apply:audit',
 NULL, NULL, 1, 2, '', NULL, NOW(), NOW(), NULL),
(1222, 1220, '0,1100,1220', '开放API回调日志', 'M', 'ProxyOpenApiCallback', 'open-api-callback', 'proxy/open-api-callback/index', NULL,
 0, 1, 1, 2, 'notification', NULL, NOW(), NOW(), NULL),
(122201, 1222, '0,1100,1220,1222', '开放API回调日志查询', 'B', NULL, '', NULL, 'openapi:callback-log:list',
 NULL, NULL, 1, 1, '', NULL, NOW(), NOW(), NULL),
(122202, 1222, '0,1100,1220,1222', '开放API回调日志重发', 'B', NULL, '', NULL, 'openapi:callback-log:retry',
 NULL, NULL, 1, 2, '', NULL, NOW(), NOW(), NULL),
(1223, 1220, '0,1100,1220', '开放API账户中心', 'M', 'ProxyOpenApiAccount', 'open-api-account', 'proxy/open-api-account/index', NULL,
 0, 1, 0, 3, 'wallet', NULL, NOW(), NOW(), NULL)
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`route_name` = VALUES(`route_name`),
`route_path` = VALUES(`route_path`),
`component` = VALUES(`component`),
`perm` = VALUES(`perm`),
`keep_alive` = VALUES(`keep_alive`),
`visible` = VALUES(`visible`),
`sort` = VALUES(`sort`),
`icon` = VALUES(`icon`),
`update_time` = NOW();

INSERT IGNORE INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES
(2, 1220), (2, 1221), (2, 122101), (2, 122102), (2, 1222), (2, 122201), (2, 122202), (2, 1223);
