import { maskSecret } from '../../../utils/masking.js'
import { createHttpError } from '../../../utils/http.js'
import type { JsonObject } from '../../../types/json.js'
import {
  findKuaishouIndustryShopConfig,
  getKuaishouIndustrySourceConfig,
  getKuaishouIndustrySourceFilePath,
  saveKuaishouIndustrySourceConfig,
  type KuaishouIndustryShopConfig,
  type KuaishouIndustrySourceConfig,
} from '../../platforms/kuaishou-industry/source-config-service.js'
import {
  exchangeKuaishouIndustryAuthorizationCode,
  refreshKuaishouIndustryAccessToken,
} from '../../platforms/kuaishou-industry/token-service.js'

const SECRET_FIELDS = ['appSecret', 'signSecret', 'messageSecret'] as const

const SHOP_SECRET_FIELDS = ['accessToken', 'refreshToken'] as const

export function getAdminKuaishouIndustrySourceConfig() {
  const config = getKuaishouIndustrySourceConfig()

  return {
    filePath: getKuaishouIndustrySourceFilePath(),
    source: mapAdminKuaishouIndustrySourceConfig(config),
  }
}

export async function updateAdminKuaishouIndustrySourceConfig(payload: JsonObject = {}) {
  const current = getKuaishouIndustrySourceConfig()
  const saved = await saveKuaishouIndustrySourceConfig({
    ...current,
    enabled: hasPayloadField(payload, 'enabled')
      ? payload.enabled !== false
      : current.enabled !== false,
    baseUrl: readConfigString(payload, 'baseUrl', current.baseUrl),
    authBaseUrl: readConfigString(payload, 'authBaseUrl', current.authBaseUrl),
    redirectUri: readConfigString(payload, 'redirectUri', current.redirectUri, {
      allowBlank: true,
    }),
    scopes: normalizeScopeText(
      readConfigString(payload, 'scopes', current.scopes, { allowBlank: true }),
    ),
    authState: readConfigString(payload, 'authState', current.authState, { allowBlank: true }),
    appKey: readConfigString(payload, 'appKey', current.appKey, { allowBlank: true }),
    openId: readConfigString(payload, 'openId', current.openId, { allowBlank: true }),
    grantedScopes: normalizeScopeText(
      readConfigString(payload, 'grantedScopes', current.grantedScopes, { allowBlank: true }),
    ),
    sellerId: readConfigString(payload, 'sellerId', current.sellerId, { allowBlank: true }),
    provider: readConfigString(payload, 'provider', current.provider),
    platform: readConfigString(payload, 'platform', current.platform),
    shopId: readConfigString(payload, 'shopId', current.shopId),
    shopName: readConfigString(payload, 'shopName', current.shopName),
    version: readConfigString(payload, 'version', current.version),
    shops: normalizeShopConfigPayloads(
      Array.isArray(payload.shops) ? payload.shops : current.shops,
      current.shops,
    ),
    ...resolveSecretPatch(payload, current),
  })

  return {
    filePath: getKuaishouIndustrySourceFilePath(),
    source: mapAdminKuaishouIndustrySourceConfig(saved),
  }
}

export async function refreshAdminKuaishouIndustryAccessToken(payload: JsonObject = {}) {
  const result = await refreshKuaishouIndustryAccessToken({
    sellerId: String(payload.sellerId || '').trim(),
  })

  return {
    filePath: getKuaishouIndustrySourceFilePath(),
    refreshed: result.refreshed,
    shop: mapAdminKuaishouIndustryShopConfig(result.shop, result.config),
    source: mapAdminKuaishouIndustrySourceConfig(result.config),
  }
}

export async function exchangeAdminKuaishouIndustryAuthorizationCode(payload: JsonObject = {}) {
  const code = String(payload.code || '').trim()
  if (!code) {
    throw createHttpError('授权 code 未填写', {
      statusCode: 400,
      errorCode: 'kuaishou_industry_missing_authorization_code',
    })
  }

  const result = await exchangeKuaishouIndustryAuthorizationCode(code, {
    sellerId: String(payload.sellerId || '').trim(),
    shopName: String(payload.shopName || '').trim(),
    customShopName: String(payload.customShopName || '').trim(),
  })

  return {
    filePath: getKuaishouIndustrySourceFilePath(),
    refreshed: result.refreshed,
    shop: mapAdminKuaishouIndustryShopConfig(result.shop, result.config),
    source: mapAdminKuaishouIndustrySourceConfig(result.config),
  }
}

function mapAdminKuaishouIndustrySourceConfig(config: KuaishouIndustrySourceConfig) {
  const primaryShop = config.shops[0] || null
  const accessTokenStatus = resolveAccessTokenStatus(primaryShop || config)

  return {
    enabled: config.enabled !== false,
    baseUrl: config.baseUrl,
    authBaseUrl: config.authBaseUrl,
    redirectUri: config.redirectUri,
    scopes: config.scopes,
    authState: config.authState,
    authorizationUrl: buildKuaishouIndustryAuthorizationUrl(config),
    appKey: config.appKey,
    appSecret: '',
    appSecretMasked: maskSecret(config.appSecret),
    hasAppSecret: Boolean(config.appSecret),
    signSecret: '',
    signSecretMasked: maskSecret(config.signSecret),
    hasSignSecret: Boolean(config.signSecret),
    messageSecret: '',
    messageSecretMasked: maskSecret(config.messageSecret),
    hasMessageSecret: Boolean(config.messageSecret),
    accessToken: '',
    accessTokenMasked: maskSecret(config.accessToken),
    hasAccessToken: Boolean(config.accessToken),
    refreshToken: '',
    refreshTokenMasked: maskSecret(config.refreshToken),
    hasRefreshToken: Boolean(config.refreshToken),
    accessTokenExpiresAt: config.accessTokenExpiresAt,
    refreshTokenExpiresAt: config.refreshTokenExpiresAt,
    accessTokenStatus: accessTokenStatus.status,
    accessTokenExpiresInSeconds: accessTokenStatus.expiresInSeconds,
    openId: config.openId,
    grantedScopes: config.grantedScopes,
    sellerId: config.sellerId,
    provider: config.provider,
    platform: config.platform,
    shopId: config.shopId,
    shopName: config.shopName,
    version: config.version,
    shops: config.shops.map((shop) => mapAdminKuaishouIndustryShopConfig(shop, config)),
    lastRefreshedAt: config.lastRefreshedAt,
    lastRefreshError: config.lastRefreshError,
  }
}

function mapAdminKuaishouIndustryShopConfig(
  shop: KuaishouIndustryShopConfig,
  config: KuaishouIndustrySourceConfig,
) {
  const accessTokenStatus = resolveAccessTokenStatus(shop)

  return {
    enabled: shop.enabled !== false,
    sellerId: shop.sellerId,
    shopId: shop.shopId,
    shopName: shop.shopName,
    customShopName: shop.customShopName,
    authState: shop.authState,
    authorizationUrl: buildKuaishouIndustryAuthorizationUrl(config, shop),
    accessToken: '',
    accessTokenMasked: maskSecret(shop.accessToken),
    hasAccessToken: Boolean(shop.accessToken),
    refreshToken: '',
    refreshTokenMasked: maskSecret(shop.refreshToken),
    hasRefreshToken: Boolean(shop.refreshToken),
    accessTokenExpiresAt: shop.accessTokenExpiresAt,
    refreshTokenExpiresAt: shop.refreshTokenExpiresAt,
    accessTokenStatus: accessTokenStatus.status,
    accessTokenExpiresInSeconds: accessTokenStatus.expiresInSeconds,
    openId: shop.openId,
    grantedScopes: shop.grantedScopes,
    lastRefreshedAt: shop.lastRefreshedAt,
    lastRefreshError: shop.lastRefreshError,
  }
}

function buildKuaishouIndustryAuthorizationUrl(
  config: KuaishouIndustrySourceConfig,
  shop?: Pick<KuaishouIndustryShopConfig, 'sellerId' | 'authState'> | null,
): string {
  if (!config.authBaseUrl || !config.appKey || !config.redirectUri || !config.scopes) {
    return ''
  }

  try {
    const url = new URL(`${String(config.authBaseUrl).replace(/\/+$/, '')}/oauth/authorize`)
    url.searchParams.set('app_id', config.appKey)
    url.searchParams.set('redirect_uri', config.redirectUri)
    url.searchParams.set('scope', normalizeScopeText(config.scopes))
    url.searchParams.set('response_type', 'code')
    const state = String(shop?.authState || config.authState || shop?.sellerId || '').trim()
    if (state) {
      url.searchParams.set('state', state)
    }

    return url.toString()
  } catch {
    return ''
  }
}

function normalizeScopeText(value: unknown): string {
  return String(value || '')
    .split(/[,\s]+/)
    .map((item) => item.trim())
    .filter(Boolean)
    .join(',')
}

function resolveSecretPatch(
  payload: JsonObject,
  current: KuaishouIndustrySourceConfig,
): Partial<KuaishouIndustrySourceConfig> {
  const patch: Partial<KuaishouIndustrySourceConfig> = {}
  for (const field of SECRET_FIELDS) {
    const text = String(payload[field] || '').trim()
    patch[field] = text || current[field]
  }

  return patch
}

function normalizeShopConfigPayloads(
  rawShops: unknown[],
  currentShops: KuaishouIndustryShopConfig[] = [],
): KuaishouIndustryShopConfig[] {
  return rawShops
    .map((rawShop, index) => normalizeShopConfigPayload(rawShop, index, currentShops))
    .filter((shop): shop is KuaishouIndustryShopConfig => Boolean(shop))
}

function normalizeShopConfigPayload(
  rawShop: unknown,
  index: number,
  currentShops: KuaishouIndustryShopConfig[],
): KuaishouIndustryShopConfig | null {
  if (!rawShop || typeof rawShop !== 'object' || Array.isArray(rawShop)) {
    return null
  }

  const payload = rawShop as JsonObject
  const current = resolveCurrentShopConfig(payload, index, currentShops)
  const sellerId = readConfigString(payload, 'sellerId', current?.sellerId || '', {
    allowBlank: true,
  })
  const shopId =
    readConfigString(payload, 'shopId', current?.shopId || sellerId, { allowBlank: true }) ||
    sellerId
  const shopName = readConfigString(payload, 'shopName', current?.shopName || '', {
    allowBlank: true,
  })
  const customShopName = readConfigString(
    payload,
    'customShopName',
    current?.customShopName || '',
    { allowBlank: true },
  )
  const accessToken = readSecretString(payload, 'accessToken', current?.accessToken || '')
  const refreshToken = readSecretString(payload, 'refreshToken', current?.refreshToken || '')
  const openId = readConfigString(payload, 'openId', current?.openId || '', { allowBlank: true })

  if (
    !sellerId &&
    !shopId &&
    !shopName &&
    !customShopName &&
    !accessToken &&
    !refreshToken &&
    !openId
  ) {
    return null
  }

  return {
    enabled: hasPayloadField(payload, 'enabled')
      ? payload.enabled !== false
      : current?.enabled !== false,
    sellerId,
    shopId,
    shopName,
    customShopName,
    authState: readConfigString(payload, 'authState', current?.authState || '', {
      allowBlank: true,
    }),
    accessToken,
    refreshToken,
    accessTokenExpiresAt: readConfigString(
      payload,
      'accessTokenExpiresAt',
      current?.accessTokenExpiresAt || '',
      { allowBlank: true },
    ),
    refreshTokenExpiresAt: readConfigString(
      payload,
      'refreshTokenExpiresAt',
      current?.refreshTokenExpiresAt || '',
      { allowBlank: true },
    ),
    openId,
    grantedScopes: normalizeScopeText(
      readConfigString(payload, 'grantedScopes', current?.grantedScopes || '', {
        allowBlank: true,
      }),
    ),
    lastRefreshedAt: readConfigString(payload, 'lastRefreshedAt', current?.lastRefreshedAt || '', {
      allowBlank: true,
    }),
    lastRefreshError: readConfigString(
      payload,
      'lastRefreshError',
      current?.lastRefreshError || '',
      { allowBlank: true },
    ),
    ...resolveShopSecretPatch(payload, current),
  }
}

function resolveCurrentShopConfig(
  payload: JsonObject,
  index: number,
  currentShops: KuaishouIndustryShopConfig[],
): KuaishouIndustryShopConfig | null {
  const sellerId = String(payload.sellerId || payload.shopId || '').trim()
  if (sellerId) {
    const sourceLike = { shops: currentShops } as KuaishouIndustrySourceConfig
    const matched = findKuaishouIndustryShopConfig(sellerId, sourceLike)
    if (matched) {
      return matched
    }
  }

  return currentShops[index] || null
}

function resolveShopSecretPatch(
  payload: JsonObject,
  current: KuaishouIndustryShopConfig | null,
): Partial<KuaishouIndustryShopConfig> {
  const patch: Partial<KuaishouIndustryShopConfig> = {}
  for (const field of SHOP_SECRET_FIELDS) {
    patch[field] = readSecretString(payload, field, current?.[field] || '')
  }

  return patch
}

function readSecretString(payload: JsonObject, field: string, fallback: string): string {
  const text = String(payload[field] || '').trim()
  return text || fallback
}

function resolveAccessTokenStatus(
  config: Pick<KuaishouIndustrySourceConfig, 'accessToken' | 'accessTokenExpiresAt'>,
) {
  if (!config.accessToken) {
    return {
      status: 'missing',
      expiresInSeconds: null,
    }
  }

  const expiresAt = Date.parse(config.accessTokenExpiresAt || '')
  if (!Number.isFinite(expiresAt)) {
    return {
      status: 'unknown',
      expiresInSeconds: null,
    }
  }

  const expiresInSeconds = Math.floor((expiresAt - Date.now()) / 1000)
  if (expiresInSeconds <= 0) {
    return {
      status: 'expired',
      expiresInSeconds,
    }
  }

  if (expiresInSeconds <= 30 * 60) {
    return {
      status: 'expiring',
      expiresInSeconds,
    }
  }

  return {
    status: 'valid',
    expiresInSeconds,
  }
}

function readConfigString(
  payload: JsonObject,
  field: string,
  fallback: string,
  options: { allowBlank?: boolean } = {},
): string {
  if (!hasPayloadField(payload, field)) {
    return fallback
  }

  const text = String(payload[field] || '').trim()
  return text || (options.allowBlank ? '' : fallback)
}

function hasPayloadField(payload: JsonObject, field: string): boolean {
  return Object.prototype.hasOwnProperty.call(payload, field)
}
