CREATE DATABASE IF NOT EXISTS hy_user DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

USE hy_user;

CREATE TABLE IF NOT EXISTS users (
  user_id BIGINT NOT NULL PRIMARY KEY,
  default_display_user_id VARCHAR(32) NOT NULL,
  current_display_user_id VARCHAR(32) NOT NULL,
  current_display_user_id_kind VARCHAR(32) NOT NULL,
  current_display_user_id_expires_at_ms BIGINT NULL,
  username VARCHAR(64) NULL,
  gender VARCHAR(32) NULL,
  country VARCHAR(64) NULL,
  region_id BIGINT NULL,
  invite_code VARCHAR(64) NULL,
  register_ip VARCHAR(64) NULL,
  register_user_agent VARCHAR(512) NULL,
  country_by_ip VARCHAR(64) NULL,
  register_device_id VARCHAR(128) NULL,
  register_device VARCHAR(128) NULL,
  os_version VARCHAR(64) NULL,
  avatar VARCHAR(512) NULL,
  birth_date DATE NULL,
  app_version VARCHAR(64) NULL,
  build_number VARCHAR(64) NULL,
  source VARCHAR(64) NULL,
  install_channel VARCHAR(64) NULL,
  campaign VARCHAR(128) NULL,
  platform VARCHAR(16) NULL,
  language VARCHAR(32) NULL,
  timezone VARCHAR(64) NULL,
  status VARCHAR(32) NOT NULL,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  UNIQUE KEY uk_users_default_display_user_id (default_display_user_id),
  UNIQUE KEY uk_users_current_display_user_id (current_display_user_id),
  KEY idx_users_status (status),
  KEY idx_users_region_status (region_id, status),
  KEY idx_users_country_region (country, region_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS countries (
  country_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  country_name VARCHAR(128) NOT NULL,
  country_code VARCHAR(3) NOT NULL,
  country_display_name VARCHAR(128) NOT NULL,
  status VARCHAR(32) NOT NULL,
  sort_order INT NOT NULL DEFAULT 0,
  created_by_user_id BIGINT NULL,
  updated_by_user_id BIGINT NULL,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  UNIQUE KEY uk_countries_code (country_code),
  KEY idx_countries_status_sort (status, sort_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS regions (
  region_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  region_code VARCHAR(64) NOT NULL,
  name VARCHAR(128) NOT NULL,
  status VARCHAR(32) NOT NULL,
  sort_order INT NOT NULL DEFAULT 0,
  created_by_user_id BIGINT NULL,
  updated_by_user_id BIGINT NULL,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  UNIQUE KEY uk_regions_code (region_code),
  KEY idx_regions_status_sort (status, sort_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS region_countries (
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  region_id BIGINT NOT NULL,
  country_code VARCHAR(3) NOT NULL,
  status VARCHAR(32) NOT NULL,
  created_by_user_id BIGINT NULL,
  updated_by_user_id BIGINT NULL,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  active_country_code VARCHAR(3)
    GENERATED ALWAYS AS (
      CASE WHEN status = 'active' THEN country_code ELSE NULL END
    ) STORED,
  UNIQUE KEY uk_region_countries_active_country (active_country_code),
  KEY idx_region_countries_country_status (country_code, status),
  KEY idx_region_countries_region_status (region_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS region_change_logs (
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  region_id BIGINT NULL,
  operation VARCHAR(64) NOT NULL,
  before_json JSON NULL,
  after_json JSON NULL,
  operator_user_id BIGINT NULL,
  request_id VARCHAR(96) NOT NULL,
  created_at_ms BIGINT NOT NULL,
  KEY idx_region_change_logs_region (region_id, created_at_ms),
  KEY idx_region_change_logs_request_id (request_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS user_region_rebuild_tasks (
  task_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  region_id BIGINT NULL,
  country_code VARCHAR(3) NOT NULL,
  target_region_id BIGINT NULL,
  mapping_revision BIGINT NOT NULL,
  status VARCHAR(32) NOT NULL,
  cursor_user_id BIGINT NOT NULL DEFAULT 0,
  locked_by VARCHAR(128) NULL,
  locked_until_ms BIGINT NULL,
  attempt_count INT NOT NULL DEFAULT 0,
  error_message VARCHAR(512) NULL,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  KEY idx_user_region_rebuild_tasks_status (status, updated_at_ms),
  KEY idx_user_region_rebuild_tasks_country (country_code, status),
  KEY idx_user_region_rebuild_tasks_lock (status, locked_until_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT IGNORE INTO countries (country_name, country_code, country_display_name, status, sort_order, created_at_ms, updated_at_ms) VALUES
  ('China', 'CN', '中国', 'active', 10, 0, 0),
  ('United States', 'US', '美国', 'active', 20, 0, 0),
  ('Japan', 'JP', '日本', 'active', 30, 0, 0),
  ('Singapore', 'SG', '新加坡', 'active', 40, 0, 0),
  ('Malaysia', 'MY', '马来西亚', 'active', 50, 0, 0),
  ('Thailand', 'TH', '泰国', 'active', 60, 0, 0),
  ('Indonesia', 'ID', '印度尼西亚', 'active', 70, 0, 0),
  ('Vietnam', 'VN', '越南', 'active', 80, 0, 0),
  ('Philippines', 'PH', '菲律宾', 'active', 90, 0, 0),
  ('Hong Kong', 'HK', '中国香港', 'active', 100, 0, 0),
  ('Macao', 'MO', '中国澳门', 'active', 110, 0, 0),
  ('Taiwan', 'TW', '中国台湾', 'active', 120, 0, 0);

CREATE TABLE IF NOT EXISTS user_display_user_ids (
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  display_user_id VARCHAR(32) NOT NULL,
  user_id BIGINT NOT NULL,
  display_user_id_kind VARCHAR(32) NOT NULL,
  status VARCHAR(32) NOT NULL,
  assigned_at_ms BIGINT NOT NULL,
  activated_at_ms BIGINT NULL,
  expires_at_ms BIGINT NULL,
  released_at_ms BIGINT NULL,
  release_reason VARCHAR(64) NULL,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  live_display_user_id VARCHAR(32)
    GENERATED ALWAYS AS (
      CASE
        WHEN status IN ('active', 'held', 'reserved', 'blocked') THEN display_user_id
        ELSE NULL
      END
    ) STORED,
  active_user_id BIGINT
    GENERATED ALWAYS AS (
      CASE WHEN status = 'active' THEN user_id ELSE NULL END
    ) STORED,
  UNIQUE KEY uk_user_display_user_ids_live (live_display_user_id),
  UNIQUE KEY uk_user_display_user_ids_active_user (active_user_id),
  KEY idx_user_display_user_ids_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS pretty_display_user_id_leases (
  lease_id VARCHAR(64) NOT NULL PRIMARY KEY,
  display_user_id VARCHAR(32) NOT NULL,
  user_id BIGINT NOT NULL,
  status VARCHAR(32) NOT NULL,
  starts_at_ms BIGINT NOT NULL,
  expires_at_ms BIGINT NOT NULL,
  payment_receipt_id VARCHAR(64) NULL,
  source VARCHAR(32) NOT NULL,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  active_display_user_id VARCHAR(32)
    GENERATED ALWAYS AS (
      CASE WHEN status = 'active' THEN display_user_id ELSE NULL END
    ) STORED,
  active_user_id BIGINT
    GENERATED ALWAYS AS (
      CASE WHEN status = 'active' THEN user_id ELSE NULL END
    ) STORED,
  UNIQUE KEY uk_pretty_display_user_id_active (active_display_user_id),
  UNIQUE KEY uk_pretty_display_user_id_active_user (active_user_id),
  KEY idx_pretty_display_user_id_leases_user (user_id, status),
  KEY idx_pretty_display_user_id_leases_expire (status, expires_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS display_user_id_change_logs (
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  user_id BIGINT NOT NULL,
  old_display_user_id VARCHAR(32) NOT NULL,
  new_display_user_id VARCHAR(32) NOT NULL,
  old_display_user_id_kind VARCHAR(32) NOT NULL,
  new_display_user_id_kind VARCHAR(32) NOT NULL,
  change_type VARCHAR(32) NOT NULL,
  lease_id VARCHAR(64) NULL,
  reason VARCHAR(64) NOT NULL,
  operator_user_id BIGINT NULL,
  request_id VARCHAR(96) NOT NULL,
  created_at_ms BIGINT NOT NULL,
  KEY idx_display_user_id_change_logs_user_id (user_id),
  KEY idx_display_user_id_change_logs_request_id (request_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS user_country_change_logs (
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  user_id BIGINT NOT NULL,
  old_country VARCHAR(64) NULL,
  new_country VARCHAR(64) NOT NULL,
  request_id VARCHAR(96) NOT NULL,
  changed_at_ms BIGINT NOT NULL,
  KEY idx_user_country_change_logs_user_changed (user_id, changed_at_ms),
  KEY idx_user_country_change_logs_request_id (request_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS password_accounts (
  user_id BIGINT NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  hash_alg VARCHAR(32) NOT NULL,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  PRIMARY KEY (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS third_party_identities (
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  user_id BIGINT NOT NULL,
  provider VARCHAR(64) NOT NULL,
  provider_subject VARCHAR(191) NOT NULL,
  provider_union_id VARCHAR(191) NULL,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  UNIQUE KEY uk_third_party_provider_subject (provider, provider_subject),
  KEY idx_third_party_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS auth_sessions (
  session_id VARCHAR(96) NOT NULL PRIMARY KEY,
  user_id BIGINT NOT NULL,
  refresh_token_hash VARCHAR(128) NOT NULL,
  device_id VARCHAR(128) NOT NULL,
  expires_at_ms BIGINT NOT NULL,
  revoked_at_ms BIGINT NULL,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  UNIQUE KEY uk_auth_sessions_refresh_token_hash (refresh_token_hash),
  KEY idx_auth_sessions_user_id (user_id),
  KEY idx_auth_sessions_expires_at (expires_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS login_audit (
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  request_id VARCHAR(96) NOT NULL,
  user_id BIGINT NULL,
  login_type VARCHAR(32) NOT NULL,
  provider VARCHAR(64) NULL,
  result VARCHAR(32) NOT NULL,
  failure_code VARCHAR(64) NULL,
  client_ip VARCHAR(64) NULL,
  user_agent VARCHAR(512) NULL,
  created_at_ms BIGINT NOT NULL,
  KEY idx_login_audit_user_id (user_id),
  KEY idx_login_audit_request_id (request_id),
  KEY idx_login_audit_created_at (created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
