import { app, safeStorage } from 'electron'
import { readFile, writeFile } from 'fs/promises'
import { join } from 'path'

import type { ModelConfig } from '../types/model'
import type {
  ClassTypeConfig,
  LoadSettingsResponse,
  SaveSettingsResponse,
  SettingsFile,
  StoredApiKey
} from '../types/settings'

export const DEFAULT_CLASS_TYPE_CONFIGS: ClassTypeConfig[] = [
  {
    id: 'cheap',
    label: '便宜班',
    courseContent:
      '本期开展了小袋鼠整合主题课程：(语言、社会、科学、健康、艺术）、生活数学；特色课程（英语、体能、美工、篮球）。'
  },
  {
    id: 'noble',
    label: '贵族班',
    courseContent:
      '本学期开展了柏克莱主题课程（语言、社会、科学、艺术、健康）；英语及特色课程（体能、舞蹈、美工、魔力猴、足球、国学）。'
  },
  {
    id: 'big',
    label: '大大班',
    courseContent:
      '本学期开展了双木桥主题课程（图说汉字、妙趣汉音、情智阅读、麦斯思维、专注力训练）；英语及特色课程（体能、舞蹈、美工、魔力猴、足球、国学）。'
  }
]

function getSettingsPath(): string {
  return join(app.getPath('userData'), 'settings.json')
}

function encodeApiKey(apiKey: string): StoredApiKey {
  if (safeStorage.isEncryptionAvailable()) {
    return {
      encoding: 'safeStorage',
      value: safeStorage.encryptString(apiKey).toString('base64')
    }
  }

  return {
    encoding: 'plain',
    value: apiKey
  }
}

function decodeApiKey(apiKey?: StoredApiKey): string {
  if (!apiKey) return ''

  if (apiKey.encoding === 'safeStorage') {
    return safeStorage.decryptString(Buffer.from(apiKey.value, 'base64'))
  }

  return apiKey.value
}

function normalizeClassTypeConfig(config: Partial<ClassTypeConfig>): ClassTypeConfig | null {
  const id = config.id?.trim()
  const label = config.label?.trim()

  if (!id || !label) {
    return null
  }

  return {
    id,
    label,
    courseContent: config.courseContent?.trim() ?? ''
  }
}

function normalizeClassTypeConfigs(configs?: Partial<ClassTypeConfig>[]): ClassTypeConfig[] {
  const normalizedConfigs =
    configs
      ?.map((config) => normalizeClassTypeConfig(config))
      .filter((config): config is ClassTypeConfig => config !== null) ?? []

  if (normalizedConfigs.length === 0) {
    return DEFAULT_CLASS_TYPE_CONFIGS
  }

  return Array.from(new Map(normalizedConfigs.map((config) => [config.id, config])).values())
}

async function readSettingsFile(): Promise<SettingsFile> {
  const raw = await readFile(getSettingsPath(), 'utf-8').catch((error: NodeJS.ErrnoException) => {
    if (error.code === 'ENOENT') return null
    throw error
  })

  if (!raw) {
    return {}
  }

  return JSON.parse(raw) as SettingsFile
}

async function writeSettingsFile(settings: SettingsFile): Promise<void> {
  await writeFile(getSettingsPath(), JSON.stringify(settings, null, 2), 'utf-8')
}

export async function loadSettings(): Promise<LoadSettingsResponse> {
  try {
    const settings = await readSettingsFile()
    const classTypeConfigs = normalizeClassTypeConfigs(settings.classTypeConfigs)

    if (!settings.modelConfig) {
      return { ok: true, modelConfig: null, classTypeConfigs }
    }

    const { apiKey, ...modelConfig } = settings.modelConfig

    return {
      ok: true,
      classTypeConfigs,
      modelConfig: {
        ...modelConfig,
        apiKey: decodeApiKey(apiKey)
      }
    }
  } catch (error) {
    return {
      ok: false,
      message: error instanceof Error ? error.message : '读取配置失败'
    }
  }
}

export async function saveSettings(modelConfig: ModelConfig): Promise<SaveSettingsResponse> {
  try {
    const currentSettings = await readSettingsFile()
    const settings: SettingsFile = {
      ...currentSettings,
      modelConfig: {
        provider: modelConfig.provider,
        baseUrl: modelConfig.baseUrl,
        model: modelConfig.model,
        temperature: modelConfig.temperature,
        maxTokens: modelConfig.maxTokens,
        systemPrompt: modelConfig.systemPrompt,
        apiKey: encodeApiKey(modelConfig.apiKey)
      }
    }

    await writeSettingsFile(settings)

    return { ok: true }
  } catch (error) {
    return {
      ok: false,
      message: error instanceof Error ? error.message : '保存配置失败'
    }
  }
}

export async function saveClassTypeConfigs(
  classTypeConfigs: ClassTypeConfig[]
): Promise<SaveSettingsResponse> {
  try {
    const currentSettings = await readSettingsFile()
    const settings: SettingsFile = {
      ...currentSettings,
      classTypeConfigs: normalizeClassTypeConfigs(classTypeConfigs)
    }

    await writeSettingsFile(settings)

    return { ok: true }
  } catch (error) {
    return {
      ok: false,
      message: error instanceof Error ? error.message : '保存班级类型配置失败'
    }
  }
}
