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

import { APP_CONFIG_KEYS } from '../../../config/app-config-keys.js'
import {
  hasAppConfigEntry,
  readAppConfigEntry,
  saveAppConfigEntry,
} from '../../config/app-config-store.js'

const AFFILIATE_DASH_CONFIG_KEY = APP_CONFIG_KEYS.affiliateDash

export type AffiliateDashSourceConfig = {
  enabled: boolean
  baseUrl: string
  appKey: string
  appSecret: string
  callbackSecret: string
  timeoutMs: number
  notifyUrl: string
  timestampToleranceSeconds: number
  preferredMatchEnabled: boolean
  skuMapping: AffiliateDashSkuMapping
}

export function hasAffiliateDashConfig() {
  return hasAppConfigEntry(AFFILIATE_DASH_CONFIG_KEY)
}

export function getAffiliateDashSourceConfig(): AffiliateDashSourceConfig {
  return readAppConfigEntry({
    configKey: AFFILIATE_DASH_CONFIG_KEY,
    fallback: createDefaultAffiliateDashSourceConfig,
    normalize: normalizeAffiliateDashSourceConfig,
  })
}

export function saveAffiliateDashSourceConfig(
  rawValue: unknown,
): Promise<AffiliateDashSourceConfig> {
  return saveAppConfigEntry({
    configKey: AFFILIATE_DASH_CONFIG_KEY,
    value: rawValue,
    normalize: normalizeAffiliateDashSourceConfig,
  })
}

export function normalizeAffiliateDashSourceConfig(rawValue: unknown): AffiliateDashSourceConfig {
  const source = isPlainObject(rawValue) ? rawValue : {}

  return {
    enabled: source.enabled !== false,
    baseUrl: String(source.baseUrl || '')
      .trim()
      .replace(/\/+$/, ''),
    appKey: String(source.appKey || '').trim(),
    appSecret: String(source.appSecret || '').trim(),
    callbackSecret: String(source.callbackSecret || '').trim(),
    timeoutMs: normalizePositiveInteger(source.timeoutMs, 10000),
    notifyUrl: String(source.notifyUrl || '').trim(),
    timestampToleranceSeconds: normalizePositiveInteger(source.timestampToleranceSeconds, 300),
    preferredMatchEnabled: source.preferredMatchEnabled !== false,
    skuMapping: normalizeSkuMapping(source.skuMapping),
  }
}

function normalizeSkuMapping(value: unknown): AffiliateDashSkuMapping {
  if (!isPlainObject(value)) {
    return {}
  }

  const mapping: AffiliateDashSkuMapping = {}
  for (const [productNo, sku] of Object.entries(value)) {
    const key = String(productNo || '').trim()
    const skuValue = String(sku || '').trim()
    if (key && skuValue) {
      mapping[key] = skuValue
    }
  }
  return mapping
}

function createDefaultAffiliateDashSourceConfig(): AffiliateDashSourceConfig {
  return {
    enabled: true,
    baseUrl: '',
    appKey: '',
    appSecret: '',
    callbackSecret: '',
    timeoutMs: 10000,
    notifyUrl: '',
    timestampToleranceSeconds: 300,
    preferredMatchEnabled: true,
    skuMapping: {},
  }
}

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

function isPlainObject(value: unknown): value is JsonObject {
  return Object.prototype.toString.call(value) === '[object Object]'
}
