import {
  getWorkerSessionBySessionId,
  getWorkerUserById,
  listWorkerSessions,
  revokeWorkerSession,
  touchWorkerSession,
} from '../../repositories/worker-platform/index.js'
import type { JsonObject } from '../../types/json.js'
import { createHttpError } from '../../utils/http.js'
import { nowIso } from '../../utils/time.js'
import {
  ensureWorkerAuthConfigured,
  isIgnorableWorkerAuthError,
  mapWorkerUser,
  normalizeSessionVersion,
  safeCompare,
  signWorkerPayload,
} from './mappers.js'
import { getRequiredWorker, type WorkerSession } from './worker-session-context-service.js'
import { mapWorkerSession } from './worker-session-view.js'

const WORKER_MAX_DEVICES = 3

export async function logoutWorkerSession(token: unknown) {
  const normalizedToken = String(token || '').trim()
  if (!normalizedToken) {
    return { success: true, revoked: false }
  }

  try {
    const session = await verifyWorkerSessionToken(normalizedToken)
    return {
      success: true,
      revoked: await revokeWorkerSession(session.workerId, session.sessionId, nowIso()),
    }
  } catch (error) {
    if (isIgnorableWorkerAuthError(error)) {
      return { success: true, revoked: false }
    }
    throw error
  }
}

export async function verifyWorkerSessionToken(token: unknown): Promise<WorkerSession> {
  ensureWorkerAuthConfigured()
  const normalizedToken = String(token || '').trim()
  if (!normalizedToken) {
    throw createHttpError('未登录或登录已失效', {
      statusCode: 401,
      errorCode: 'worker_auth_required',
    })
  }

  const parts = normalizedToken.split('.')
  const encodedPayload = parts[0]
  const signature = parts[1]
  if (
    parts.length !== 2 ||
    !encodedPayload ||
    !signature ||
    !safeCompare(signature, signWorkerPayload(encodedPayload))
  ) {
    throw createHttpError('接单登录态无效', {
      statusCode: 401,
      errorCode: 'worker_auth_invalid',
    })
  }

  let payload: JsonObject
  try {
    payload = JSON.parse(Buffer.from(encodedPayload, 'base64url').toString('utf8'))
  } catch {
    throw createHttpError('接单登录态无效', {
      statusCode: 401,
      errorCode: 'worker_auth_invalid',
    })
  }

  if (String(payload.typ || '') !== 'worker') {
    throw createHttpError('接单登录态无效', {
      statusCode: 401,
      errorCode: 'worker_auth_invalid',
    })
  }

  const expiresAt = String(payload.exp || '').trim()
  if (!expiresAt || Date.parse(expiresAt) <= Date.now()) {
    throw createHttpError('登录已过期，请重新登录', {
      statusCode: 401,
      errorCode: 'worker_auth_expired',
    })
  }

  const workerId = Number(payload.uid || 0)
  const worker = await getWorkerUserById(workerId)
  if (!worker || worker.status !== 'active') {
    throw createHttpError('接单账号已不可用，请重新登录', {
      statusCode: 401,
      errorCode: 'worker_auth_user_invalid',
    })
  }

  const currentSessionVersion = normalizeSessionVersion(worker.session_version)
  if (Number(payload.ver || 0) !== currentSessionVersion) {
    throw createHttpError('登录态已失效，请重新登录', {
      statusCode: 401,
      errorCode: 'worker_auth_stale',
    })
  }

  const sessionId = String(payload.sid || '').trim()
  const sessionRecord = sessionId ? await getWorkerSessionBySessionId(sessionId) : null
  if (
    !sessionRecord ||
    Number(sessionRecord.worker_id) !== Number(worker.id) ||
    sessionRecord.status !== 'active' ||
    Date.parse(String(sessionRecord.expires_at || '')) <= Date.now() ||
    !(await touchWorkerSession(sessionId, nowIso()))
  ) {
    throw createHttpError('登录设备已被删除，请重新登录', {
      statusCode: 401,
      errorCode: 'worker_auth_device_revoked',
    })
  }

  return {
    sessionId,
    workerId: Number(worker.id),
    username: worker.username,
    status: worker.status,
    expiresAt,
    sessionVersion: currentSessionVersion,
  }
}

export async function getWorkerSessions(session: WorkerSession) {
  const sessions = await listWorkerSessions(session.workerId, nowIso())
  const deviceCounts = sessions.reduce(
    (counts, item) => {
      const deviceType = item.device_type === 'mobile' ? 'mobile' : 'pc'
      counts[deviceType] += 1
      return counts
    },
    { pc: 0, mobile: 0 },
  )
  return {
    maxDevices: WORKER_MAX_DEVICES,
    maxDevicesByType: { pc: WORKER_MAX_DEVICES, mobile: WORKER_MAX_DEVICES },
    deviceCounts,
    items: sessions.map((item) => mapWorkerSession(item, session.sessionId)),
  }
}

export async function deleteWorkerSession(session: WorkerSession, targetSessionId: unknown) {
  const normalizedTarget = String(targetSessionId || '').trim()
  if (!normalizedTarget) {
    throw createHttpError('缺少登录设备标识', {
      statusCode: 400,
      errorCode: 'worker_session_id_required',
    })
  }
  return {
    deleted: await revokeWorkerSession(session.workerId, normalizedTarget, nowIso()),
  }
}

export async function getWorkerSessionSummary(token: unknown) {
  const session = await verifyWorkerSessionToken(token)
  const worker = await getRequiredWorker(session.workerId)
  return {
    authenticated: true,
    expiresAt: session.expiresAt,
    worker: mapWorkerUser(worker),
  }
}
