import path from 'node:path'
import type { JsonObject } from '../../../types/json.js'

import { APP_CONFIG_KEYS } from '../../../config/app-config-keys.js'
import { PROJECT_ROOT } from '../../../config/runtime.js'
import { createHttpError } from '../../../utils/http.js'
import { readAppConfigEntry, saveAppConfigEntry } from '../../config/app-config-store.js'
import {
  DEFAULT_CLOUDTENTACLES_DEVICE_ID,
  DEFAULT_CLOUDTENTACLES_DEVICE_TYPE,
  normalizeCloudtentaclesDeviceId,
  normalizeCloudtentaclesDeviceType,
} from './defaults.js'

const CLOUDTENTACLES_SESSION_FILE_PATH = path.join(
  PROJECT_ROOT,
  'data',
  'cloudtentacles-session.json',
)

type CloudtentaclesSessionState = ReturnType<typeof createDefaultCloudtentaclesSessionState>
type CloudtentaclesSessionStatesFile = {
  sessions: Record<string, CloudtentaclesSessionState>
}

export function getCloudtentaclesSessionFilePath() {
  return CLOUDTENTACLES_SESSION_FILE_PATH
}

// 兼容旧调用：返回 key='default' 的会话。
export function getCloudtentaclesSessionState() {
  const states = loadCloudtentaclesSessionStates()
  return states.sessions['default'] || createDefaultCloudtentaclesSessionState()
}

// 按 sourceKey 获取会话，未命中时返回 null。
export function getCloudtentaclesSessionStateByKey(sourceKey: unknown) {
  const states = loadCloudtentaclesSessionStates()
  const key = String(sourceKey || '').trim()
  if (!key) return null
  return states.sessions[key] || null
}

// 返回所有账号的会话状态。
export function getAllCloudtentaclesSessionStates() {
  return loadCloudtentaclesSessionStates()
}

// 兼容旧保存格式：支持单会话对象和 sessions 映射。
export function saveCloudtentaclesSessionState(rawValue: unknown) {
  const normalized = normalizeSessionStatesFile(rawValue)
  return saveAppConfigEntry({
    configKey: APP_CONFIG_KEYS.cloudtentaclesSession,
    legacyFilePath: CLOUDTENTACLES_SESSION_FILE_PATH,
    value: normalized,
    normalize: normalizeSessionStatesFile,
  })
}

// 保存指定 sourceKey 的会话。
export async function saveCloudtentaclesSessionStateByKey(sourceKey: unknown, rawValue: unknown) {
  const key = String(sourceKey || '').trim()
  if (!key) {
    throw createHttpError('cloudtentacles sourceKey 不能为空', {
      statusCode: 400,
      errorCode: 'cloudtentacles_source_key_required',
    })
  }

  const states = loadCloudtentaclesSessionStates()
  states.sessions[key] = normalizeCloudtentaclesSessionState(rawValue)

  await saveCloudtentaclesSessionState(states)
  return states.sessions[key]
}

// 删除指定 sourceKey 的会话。
export async function deleteCloudtentaclesSessionStateByKey(sourceKey: unknown) {
  const key = String(sourceKey || '').trim()
  if (!key) {
    throw createHttpError('cloudtentacles sourceKey 不能为空', {
      statusCode: 400,
      errorCode: 'cloudtentacles_source_key_required',
    })
  }

  const states = loadCloudtentaclesSessionStates()
  delete states.sessions[key]

  await saveCloudtentaclesSessionState(states)
  return states
}

// 兼容旧调用：只清理 default 会话。
export function clearCloudtentaclesSessionState() {
  return clearCloudtentaclesSessionStateByKey('default')
}

// 清理指定 sourceKey 的会话，重置为空状态。
export async function clearCloudtentaclesSessionStateByKey(sourceKey: unknown) {
  const key = String(sourceKey || '').trim()
  if (!key) {
    throw createHttpError('cloudtentacles sourceKey 不能为空', {
      statusCode: 400,
      errorCode: 'cloudtentacles_source_key_required',
    })
  }

  const cleared = createDefaultCloudtentaclesSessionState()
  await saveCloudtentaclesSessionStateByKey(key, cleared)
  return cleared
}

// 只保留仍存在 source 配置的会话。
export async function pruneCloudtentaclesSessionStates(sourceKeys: unknown[] = []) {
  const allowedKeys = new Set(
    Array.isArray(sourceKeys)
      ? sourceKeys.map((value) => String(value || '').trim()).filter(Boolean)
      : [],
  )

  const states = loadCloudtentaclesSessionStates()
  states.sessions = Object.fromEntries(
    Object.entries(states.sessions || {}).filter(([key]) =>
      allowedKeys.has(String(key || '').trim()),
    ),
  )

  await saveCloudtentaclesSessionState(states)
  return states
}

function loadCloudtentaclesSessionStates(): CloudtentaclesSessionStatesFile {
  return readAppConfigEntry({
    configKey: APP_CONFIG_KEYS.cloudtentaclesSession,
    legacyFilePath: CLOUDTENTACLES_SESSION_FILE_PATH,
    fallback: createDefaultCloudtentaclesSessionStates,
    normalize: normalizeSessionStatesFile,
  })
}

// 标准化单个会话状态。
function normalizeCloudtentaclesSessionState(rawValue: unknown) {
  const source = isPlainObject(rawValue) ? rawValue : {}

  return {
    token: String(source.token || '').trim(),
    baseUrl: String(source.baseUrl || '').trim(),
    username: String(source.username || '').trim(),
    phone: String(source.phone || '').trim(),
    loggedInAt: String(source.loggedInAt || '').trim(),
    deviceId: normalizeCloudtentaclesDeviceId(source.deviceId),
    deviceType: normalizeCloudtentaclesDeviceType(source.deviceType),
  }
}

// 标准化整体会话状态，同时兼容旧版单会话对象。
export function normalizeSessionStatesFile(rawValue: unknown): CloudtentaclesSessionStatesFile {
  if (isPlainObject(rawValue) && !rawValue.sessions) {
    return {
      sessions: {
        default: normalizeCloudtentaclesSessionState(rawValue),
      },
    }
  }

  return {
    sessions:
      isPlainObject(rawValue) && isPlainObject(rawValue.sessions)
        ? Object.fromEntries(
            Object.entries(rawValue.sessions).map(([k, v]) => [
              k,
              normalizeCloudtentaclesSessionState(v),
            ]),
          )
        : {},
  }
}

function createDefaultCloudtentaclesSessionState() {
  return {
    token: '',
    baseUrl: '',
    username: '',
    phone: '',
    loggedInAt: '',
    deviceId: DEFAULT_CLOUDTENTACLES_DEVICE_ID,
    deviceType: DEFAULT_CLOUDTENTACLES_DEVICE_TYPE,
  }
}

function createDefaultCloudtentaclesSessionStates(): CloudtentaclesSessionStatesFile {
  return {
    sessions: {
      default: createDefaultCloudtentaclesSessionState(),
    },
  }
}

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