/**
 * Session Service — 会话 CRUD + 消息持久化
 *
 * 管理会话的创建、查询、更新、删除，以及消息的存取。
 * 所有操作通过 better-sqlite3 同步执行。
 *
 * @see docs/MetonaAI-Desktop 架构与交互设计.html
 */

import { nanoid } from 'nanoid';
import type Database from 'better-sqlite3';
import log from 'electron-log';

// ===== 类型定义 =====

export interface SessionRow {
  id: string;
  title: string;
  created_at: number;
  updated_at: number;
  message_count: number;
  total_tokens: number;
  pinned: number;
  archived: number;
  metadata: string;
}

export interface MessageRow {
  id: string;
  session_id: string;
  role: string;
  content: string;
  reasoning_content: string | null;
  tool_calls: string | null;
  tool_result: string | null;
  attachments: string | null;
  iteration: number | null;
  created_at: number;
}

export interface SessionInfo {
  id: string;
  title: string;
  createdAt: number;
  updatedAt: number;
  messageCount: number;
  totalTokens: number;
  pinned: boolean;
  archived: boolean;
}

export interface MessageInfo {
  id: string;
  role: string;
  content: string;
  reasoningContent?: string;
  toolCalls?: unknown[];
  toolResult?: unknown;
  attachments?: unknown[];
  iteration?: number;
  timestamp: number;
}

// ===== 服务类 =====

export class SessionService {
  /**
   * 获取数据库实例
   */
  getDB(): Database.Database {
    return this.getDBFn();
  }

  constructor(private getDBFn: () => Database.Database) {}

  /**
   * 列出所有会话
   */
  list(options?: { archived?: boolean }): SessionInfo[] {
    const db = this.getDBFn();
    const archived = options?.archived ?? false;

    const rows = db.prepare(`
      SELECT * FROM sessions
      WHERE archived = ?
      ORDER BY pinned DESC, updated_at DESC
    `).all(archived ? 1 : 0) as SessionRow[];

    return rows.map(this.toSessionInfo);
  }

  /**
   * 创建新会话
   */
  create(title?: string): SessionInfo {
    const db = this.getDBFn();
    const id = `s_${nanoid(12)}`;
    const now = Date.now();
    const sessionTitle = title ?? '新会话';

    db.prepare(`
      INSERT INTO sessions (id, title, created_at, updated_at)
      VALUES (?, ?, ?, ?)
    `).run(id, sessionTitle, now, now);

    log.info(`Session created: ${id} (${sessionTitle})`);

    return {
      id,
      title: sessionTitle,
      createdAt: now,
      updatedAt: now,
      messageCount: 0,
      totalTokens: 0,
      pinned: false,
      archived: false,
    };
  }

  /**
   * 重命名会话
   */
  rename(sessionId: string, title: string): boolean {
    const db = this.getDBFn();
    const result = db.prepare(`
      UPDATE sessions SET title = ?, updated_at = ? WHERE id = ?
    `).run(title, Date.now(), sessionId);

    if (result.changes > 0) {
      log.info(`Session renamed: ${sessionId} → ${title}`);
      return true;
    }
    return false;
  }

  /**
   * 删除会话（级联删除消息）
   */
  delete(sessionId: string): boolean {
    const db = this.getDBFn();
    const result = db.prepare('DELETE FROM sessions WHERE id = ?').run(sessionId);

    if (result.changes > 0) {
      log.info(`Session deleted: ${sessionId}`);
      return true;
    }
    return false;
  }

  /**
   * 置顶/取消置顶
   */
  pin(sessionId: string, pinned: boolean): boolean {
    const db = this.getDBFn();
    const result = db.prepare(`
      UPDATE sessions SET pinned = ?, updated_at = ? WHERE id = ?
    `).run(pinned ? 1 : 0, Date.now(), sessionId);

    return result.changes > 0;
  }

  /**
   * 归档/取消归档
   */
  archive(sessionId: string, archived: boolean): boolean {
    const db = this.getDBFn();
    const result = db.prepare(`
      UPDATE sessions SET archived = ?, updated_at = ? WHERE id = ?
    `).run(archived ? 1 : 0, Date.now(), sessionId);

    return result.changes > 0;
  }

  /**
   * 获取会话消息列表
   */
  getMessages(sessionId: string): MessageInfo[] {
    const db = this.getDBFn();

    const rows = db.prepare(`
      SELECT * FROM messages
      WHERE session_id = ?
      ORDER BY created_at ASC
    `).all(sessionId) as MessageRow[];

    return rows.map(this.toMessageInfo);
  }

  /**
   * 保存一条消息
   */
  saveMessage(params: {
    sessionId: string;
    role: string;
    content: string;
    reasoningContent?: string;
    toolCalls?: unknown[];
    toolResult?: unknown;
    attachments?: unknown[];
    iteration?: number;
  }): MessageInfo {
    const db = this.getDBFn();
    const id = `msg_${nanoid(12)}`;
    const now = Date.now();

    db.prepare(`
      INSERT INTO messages (id, session_id, role, content, reasoning_content, tool_calls, tool_result, attachments, iteration, created_at)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `).run(
      id,
      params.sessionId,
      params.role,
      params.content,
      params.reasoningContent ?? null,
      params.toolCalls ? JSON.stringify(params.toolCalls) : null,
      params.toolResult ? JSON.stringify(params.toolResult) : null,
      params.attachments ? JSON.stringify(params.attachments) : null,
      params.iteration ?? null,
      now,
    );

    // 更新会话的 updated_at 和 message_count
    db.prepare(`
      UPDATE sessions
      SET updated_at = ?, message_count = message_count + 1
      WHERE id = ?
    `).run(now, params.sessionId);

    return {
      id,
      role: params.role,
      content: params.content,
      reasoningContent: params.reasoningContent,
      toolCalls: params.toolCalls,
      toolResult: params.toolResult,
      attachments: params.attachments,
      iteration: params.iteration,
      timestamp: now,
    };
  }

  /**
   * 更新会话 Token 统计
   */
  updateTokenUsage(sessionId: string, tokens: number): void {
    const db = this.getDBFn();
    db.prepare(`
      UPDATE sessions SET total_tokens = total_tokens + ? WHERE id = ?
    `).run(tokens, sessionId);
  }

  /**
   * 删除一条消息
   */
  deleteMessage(messageId: string): boolean {
    const db = this.getDBFn();
    const result = db.prepare('DELETE FROM messages WHERE id = ?').run(messageId);
    return result.changes > 0;
  }

  /**
   * 清空会话所有消息
   */
  clearMessages(sessionId: string): boolean {
    const db = this.getDBFn();
    const result = db.prepare('DELETE FROM messages WHERE session_id = ?').run(sessionId);
    db.prepare('UPDATE sessions SET message_count = 0, updated_at = ? WHERE id = ?').run(Date.now(), sessionId);
    return result.changes > 0;
  }

  /**
   * 保存会话的 trace 步骤和 token 用量（存入 metadata JSON）
   */
  saveTraceData(sessionId: string, data: { traceSteps: unknown[]; tokenUsage: unknown }): void {
    const db = this.getDBFn();
    const metadata = JSON.stringify({ traceSteps: data.traceSteps, tokenUsage: data.tokenUsage });
    db.prepare(`
      UPDATE sessions SET metadata = ?, updated_at = ? WHERE id = ?
    `).run(metadata, Date.now(), sessionId);
  }

  /**
   * 加载会话的 trace 步骤和 token 用量
   */
  getTraceData(sessionId: string): { traceSteps: unknown[]; tokenUsage: unknown } | null {
    const db = this.getDBFn();
    const row = db.prepare('SELECT metadata FROM sessions WHERE id = ?').get(sessionId) as { metadata: string } | undefined;
    if (!row?.metadata) return null;
    try {
      const data = JSON.parse(row.metadata);
      if (data.traceSteps || data.tokenUsage) return data;
      return null;
    } catch {
      return null;
    }
  }

  // ===== 私有转换方法 =====

  private toSessionInfo(row: SessionRow): SessionInfo {
    return {
      id: row.id,
      title: row.title,
      createdAt: row.created_at,
      updatedAt: row.updated_at,
      messageCount: row.message_count,
      totalTokens: row.total_tokens,
      pinned: row.pinned === 1,
      archived: row.archived === 1,
    };
  }

  private toMessageInfo(row: MessageRow): MessageInfo {
    return {
      id: row.id,
      role: row.role,
      content: row.content,
      reasoningContent: row.reasoning_content ?? undefined,
      toolCalls: row.tool_calls ? JSON.parse(row.tool_calls) : undefined,
      toolResult: row.tool_result ? JSON.parse(row.tool_result) : undefined,
      attachments: row.attachments ? JSON.parse(row.attachments) : undefined,
      iteration: row.iteration ?? undefined,
      timestamp: row.created_at,
    };
  }
}
