import { runtimeConfig } from '../../../config/runtime.js'
import type { JsonObject } from '../../../types/json.js'

import type { RuntimeConfig } from '../../../types/runtime-config.js'
import {
  DEFAULT_CLOUDTENTACLES_DEVICE_ID,
  DEFAULT_CLOUDTENTACLES_DEVICE_TYPE,
  normalizeCloudtentaclesDeviceId,
  normalizeCloudtentaclesDeviceType,
} from './defaults.js'

type CloudtentaclesRuntimeConfig = RuntimeConfig['platforms']['cloudtentacles']
export function resolveCloudtentaclesConfig(overrides: Partial<CloudtentaclesRuntimeConfig> = {}) {
  const baseConfig = runtimeConfig.platforms?.cloudtentacles || {
    baseUrl: '',
    timeoutMs: 5000,
    sendSmsPath: '/public/verif_code',
    loginPath: '/public/login',
    userInfoPath: '/user/info',
    assetPath: '/user/get_asset',
    permissionPath: '/user/get_permission',
    categoriesPath: '/categories/get',
    skuListPath: '/sku/list',
    skuBuyPath: '/sku/buy',
    skuUsePath: '/sku/use',
    knapsackPath: '/user/get_knapsack',
    vnListPath: '/vn/list',
    vnAppointPath: '/vn/appoint',
    vnGenerateLoginCodePath: '/vn/generate_login_code',
    vnVerifCodePath: '/public/vn_verif_code',
    vnVerifyLoginCodePath: '/vn/verify_login_code',
    vnBindUrlPath: '/vn/bind_url',
    vnBindInfoPath: '/vn/bind_info',
    vnBackPath: '/vn/back',
    bindUrlTtlSeconds: 600,
    bindUrlProbeIntervalSeconds: 30,
    bindUrlProbeTimeoutMs: 5000,
    bindUrlProbeUserAgent: '',
    bindUrlProbeEndpoint: 'https://comm.ams.game.qq.com/ide/',
    bindUrlProbeChartId: '323794',
    bindUrlProbeSubChartId: '323794',
    bindUrlProbeIdeToken: 'z90Syo',
    bindUrlProbeActivityUrl: 'http%3A%2F%2Fgp.qq.com%2Fcp%2Fa20240828cmcc%2F',
    bindUrlProbeReferer: 'https://gp.qq.com/',
    bindUrlProbeExtraCookie: '',
    publicKeyPem: '',
    clientSource: 'ct-client',
    deviceId: DEFAULT_CLOUDTENTACLES_DEVICE_ID,
    deviceType: DEFAULT_CLOUDTENTACLES_DEVICE_TYPE,
  }

  return {
    baseUrl: normalizeBaseUrl(overrides.baseUrl || baseConfig.baseUrl || 'https://123.207.217.176'),
    timeoutMs: normalizePositiveInteger(overrides.timeoutMs || baseConfig.timeoutMs, 5000),
    sendSmsPath: normalizePath(
      overrides.sendSmsPath || baseConfig.sendSmsPath,
      '/public/verif_code',
    ),
    loginPath: normalizePath(overrides.loginPath || baseConfig.loginPath, '/public/login'),
    userInfoPath: normalizePath(overrides.userInfoPath || baseConfig.userInfoPath, '/user/info'),
    assetPath: normalizePath(overrides.assetPath || baseConfig.assetPath, '/user/get_asset'),
    permissionPath: normalizePath(
      overrides.permissionPath || baseConfig.permissionPath,
      '/user/get_permission',
    ),
    categoriesPath: normalizePath(
      overrides.categoriesPath || baseConfig.categoriesPath,
      '/categories/get',
    ),
    skuListPath: normalizePath(overrides.skuListPath || baseConfig.skuListPath, '/sku/list'),
    skuBuyPath: normalizePath(overrides.skuBuyPath || baseConfig.skuBuyPath, '/sku/buy'),
    skuUsePath: normalizePath(overrides.skuUsePath || baseConfig.skuUsePath, '/sku/use'),
    knapsackPath: normalizePath(
      overrides.knapsackPath || baseConfig.knapsackPath,
      '/user/get_knapsack',
    ),
    vnListPath: normalizePath(overrides.vnListPath || baseConfig.vnListPath, '/vn/list'),
    vnAppointPath: normalizePath(
      overrides.vnAppointPath || baseConfig.vnAppointPath,
      '/vn/appoint',
    ),
    vnGenerateLoginCodePath: normalizePath(
      overrides.vnGenerateLoginCodePath || baseConfig.vnGenerateLoginCodePath,
      '/vn/generate_login_code',
    ),
    vnVerifCodePath: normalizePath(
      overrides.vnVerifCodePath || baseConfig.vnVerifCodePath,
      '/public/vn_verif_code',
    ),
    vnVerifyLoginCodePath: normalizePath(
      overrides.vnVerifyLoginCodePath || baseConfig.vnVerifyLoginCodePath,
      '/vn/verify_login_code',
    ),
    vnBindUrlPath: normalizePath(
      overrides.vnBindUrlPath || baseConfig.vnBindUrlPath,
      '/vn/bind_url',
    ),
    vnBindInfoPath: normalizePath(
      overrides.vnBindInfoPath || baseConfig.vnBindInfoPath,
      '/vn/bind_info',
    ),
    vnBackPath: normalizePath(overrides.vnBackPath || baseConfig.vnBackPath, '/vn/back'),
    bindUrlTtlSeconds: normalizePositiveInteger(
      overrides.bindUrlTtlSeconds || baseConfig.bindUrlTtlSeconds,
      600,
    ),
    bindUrlProbeIntervalSeconds: normalizePositiveInteger(
      overrides.bindUrlProbeIntervalSeconds || baseConfig.bindUrlProbeIntervalSeconds,
      30,
    ),
    bindUrlProbeTimeoutMs: normalizePositiveInteger(
      overrides.bindUrlProbeTimeoutMs || baseConfig.bindUrlProbeTimeoutMs,
      5000,
    ),
    bindUrlProbeUserAgent: String(
      overrides.bindUrlProbeUserAgent || baseConfig.bindUrlProbeUserAgent || '',
    ).trim(),
    bindUrlProbeEndpoint: String(
      overrides.bindUrlProbeEndpoint ||
        baseConfig.bindUrlProbeEndpoint ||
        'https://comm.ams.game.qq.com/ide/',
    ).trim(),
    bindUrlProbeChartId: String(
      overrides.bindUrlProbeChartId || baseConfig.bindUrlProbeChartId || '323794',
    ).trim(),
    bindUrlProbeSubChartId: String(
      overrides.bindUrlProbeSubChartId || baseConfig.bindUrlProbeSubChartId || '323794',
    ).trim(),
    bindUrlProbeIdeToken: String(
      overrides.bindUrlProbeIdeToken || baseConfig.bindUrlProbeIdeToken || 'z90Syo',
    ).trim(),
    bindUrlProbeActivityUrl: String(
      overrides.bindUrlProbeActivityUrl ||
        baseConfig.bindUrlProbeActivityUrl ||
        'http%3A%2F%2Fgp.qq.com%2Fcp%2Fa20240828cmcc%2F',
    ).trim(),
    bindUrlProbeReferer: String(
      overrides.bindUrlProbeReferer || baseConfig.bindUrlProbeReferer || 'https://gp.qq.com/',
    ).trim(),
    bindUrlProbeExtraCookie: String(
      overrides.bindUrlProbeExtraCookie || baseConfig.bindUrlProbeExtraCookie || '',
    ).trim(),
    publicKeyPem: normalizePem(overrides.publicKeyPem || baseConfig.publicKeyPem),
    clientSource:
      String(overrides.clientSource || baseConfig.clientSource || 'ct-client').trim() ||
      'ct-client',
    deviceId: normalizeCloudtentaclesDeviceId(overrides.deviceId ?? baseConfig.deviceId),
    deviceType: normalizeCloudtentaclesDeviceType(overrides.deviceType ?? baseConfig.deviceType),
  }
}

export function buildCloudtentaclesUrl(
  baseUrl: unknown,
  pathname: unknown,
  searchParams: JsonObject | null = null,
) {
  const url = new URL(
    normalizePath(pathname, '/'),
    normalizeBaseUrl(baseUrl) || 'https://123.207.217.176',
  )

  if (searchParams && typeof searchParams === 'object') {
    for (const [key, value] of Object.entries(searchParams)) {
      if (typeof value === 'undefined' || value === null || value === '') {
        continue
      }
      url.searchParams.set(key, String(value))
    }
  }

  return url
}

export function buildCloudtentaclesHeaders({
  token = '',
  contentType = 'application/json',
  deviceId = DEFAULT_CLOUDTENTACLES_DEVICE_ID,
  deviceType = DEFAULT_CLOUDTENTACLES_DEVICE_TYPE,
  extra = {},
}: {
  token?: unknown
  contentType?: string
  deviceId?: unknown
  deviceType?: unknown
  extra?: JsonObject
} = {}) {
  const headers: JsonObject = {
    accept: 'application/json, text/plain, */*',
    ...(contentType ? { 'content-type': contentType } : {}),
    deviceid: normalizeCloudtentaclesDeviceId(deviceId),
    devicetype: String(normalizeCloudtentaclesDeviceType(deviceType)),
    ...normalizeHeaderMap(extra),
  }

  const normalizedToken = String(token || '').trim()
  if (normalizedToken) {
    headers.authorization = normalizedToken
  }

  return headers
}

function normalizeBaseUrl(value: unknown) {
  return String(value || '')
    .trim()
    .replace(/\/+$/, '')
}

function normalizePath(value: unknown, fallback: string) {
  const normalized = String(value || '').trim()
  if (!normalized) {
    return fallback
  }

  return normalized.startsWith('/') ? normalized : `/${normalized}`
}

function normalizePositiveInteger(value: unknown, fallback: number) {
  const parsed = Number(value)
  return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback
}

function normalizeHeaderMap(extra: unknown) {
  if (!extra || typeof extra !== 'object') {
    return {}
  }

  return Object.fromEntries(
    Object.entries(extra)
      .map(([key, value]) => [
        String(key || '')
          .trim()
          .toLowerCase(),
        String(value || '').trim(),
      ])
      .filter(([key, value]) => key && value),
  )
}

function normalizePem(value: unknown) {
  return String(value || '')
    .replace(/\r/g, '')
    .split('\n')
    .map((line) => line.trim())
    .filter(Boolean)
    .join('\n')
}
