import { APP_CONFIG_KEYS } from '../../config/app-config-keys.js'
import type { JsonObject } from '../../types/json.js'
import { readAppConfigEntry, saveAppConfigEntry } from '../config/app-config-store.js'
import {
  normalizeStoredFileUrl,
  refreshUploadedFileUrls,
  type UploadedFileDto,
} from '../file-storage/file-storage-service.js'

export type WorkerFinanceConfig = {
  depositUnfreezeDays: number
  rewardUnfreezeEnabled: boolean
  recharge: {
    enabled: boolean
    channelName: string
    accountName: string
    accountNo: string
    qrCodeImage: UploadedFileDto | null
    instructions: string
  }
  adminContact: {
    wechatQrCodeImage: UploadedFileDto | null
  }
  withdraw: {
    enabled: boolean
    instructions: string
  }
}

export function getWorkerFinanceConfig(): WorkerFinanceConfig {
  const config = readAppConfigEntry({
    configKey: APP_CONFIG_KEYS.workerFinance,
    fallback: createDefaultWorkerFinanceConfig,
    normalize: normalizeWorkerFinanceConfig,
  })
  return refreshWorkerFinanceConfig(config)
}

export async function saveWorkerFinanceConfig(rawValue: unknown): Promise<WorkerFinanceConfig> {
  const saved = await saveAppConfigEntry({
    configKey: APP_CONFIG_KEYS.workerFinance,
    value: rawValue,
    normalize: normalizeWorkerFinanceConfig,
  })
  return refreshWorkerFinanceConfig(saved)
}

export function normalizeWorkerFinanceConfig(rawValue: unknown): WorkerFinanceConfig {
  const source = isPlainObject(rawValue) ? rawValue : {}
  const recharge = isPlainObject(source.recharge) ? source.recharge : {}
  const adminContact = isPlainObject(source.adminContact)
    ? source.adminContact
    : isPlainObject(source.admin_contact)
      ? source.admin_contact
      : {}
  const withdraw = isPlainObject(source.withdraw) ? source.withdraw : {}

  return {
    depositUnfreezeDays: normalizeRangeInteger(source.depositUnfreezeDays, 3, 0, 30),
    rewardUnfreezeEnabled: source.rewardUnfreezeEnabled !== false,
    recharge: {
      enabled: typeof recharge.enabled === 'boolean' ? recharge.enabled : true,
      channelName: String(recharge.channelName || recharge.channel_name || '').trim(),
      accountName: String(recharge.accountName || recharge.account_name || '').trim(),
      accountNo: String(recharge.accountNo || recharge.account_no || '').trim(),
      qrCodeImage: normalizeUploadedFileForStorage(recharge.qrCodeImage || recharge.qr_code_image),
      instructions: String(recharge.instructions || '').trim(),
    },
    adminContact: {
      wechatQrCodeImage: normalizeUploadedFileForStorage(
        adminContact.wechatQrCodeImage || adminContact.wechat_qr_code_image,
        '管理员微信二维码',
      ),
    },
    withdraw: {
      enabled: typeof withdraw.enabled === 'boolean' ? withdraw.enabled : true,
      instructions: String(withdraw.instructions || '').trim(),
    },
  }
}

export function createDefaultWorkerFinanceConfig(): WorkerFinanceConfig {
  return {
    depositUnfreezeDays: 3,
    rewardUnfreezeEnabled: true,
    recharge: {
      enabled: true,
      channelName: '',
      accountName: '',
      accountNo: '',
      qrCodeImage: null,
      instructions: '',
    },
    adminContact: {
      wechatQrCodeImage: null,
    },
    withdraw: {
      enabled: true,
      instructions: '',
    },
  }
}

function refreshWorkerFinanceConfig(config: WorkerFinanceConfig): WorkerFinanceConfig {
  return {
    depositUnfreezeDays: config.depositUnfreezeDays,
    rewardUnfreezeEnabled: config.rewardUnfreezeEnabled,
    recharge: {
      ...config.recharge,
      qrCodeImage: config.recharge.qrCodeImage
        ? (refreshUploadedFileUrls(config.recharge.qrCodeImage) as UploadedFileDto)
        : null,
    },
    adminContact: {
      wechatQrCodeImage: config.adminContact.wechatQrCodeImage
        ? (refreshUploadedFileUrls(config.adminContact.wechatQrCodeImage) as UploadedFileDto)
        : null,
    },
    withdraw: {
      ...config.withdraw,
    },
  }
}

function normalizeRangeInteger(value: unknown, fallback: number, min: number, max: number) {
  const parsed = Number(value)
  if (!Number.isInteger(parsed)) {
    return fallback
  }
  return Math.min(max, Math.max(min, parsed))
}

function normalizeUploadedFileForStorage(
  value: unknown,
  fallbackFilename = '收款二维码',
): UploadedFileDto | null {
  if (!isPlainObject(value)) {
    return null
  }

  const objectKey = String(value.objectKey || value.object_key || '').trim()
  if (!objectKey) {
    return null
  }

  return {
    objectKey,
    url: normalizeStoredFileUrl(value.url, objectKey),
    thumbnailUrl: normalizeStoredFileUrl(value.thumbnailUrl || value.thumbnail_url, objectKey),
    mediumUrl: normalizeStoredFileUrl(value.mediumUrl || value.medium_url, objectKey),
    filename: String(value.filename || '').trim() || fallbackFilename,
    contentType: String(value.contentType || value.content_type || '').trim(),
    size: Math.max(0, Number(value.size || 0) || 0),
  }
}

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