import { db, schema } from 'officerdb';
import type { TaskInfo } from '@@/api/chat-types';

type ChatMessage =
  | { role: 'user'; text: string }
  | { role: 'assistant'; text: string }
  | {
      role: 'tool';
      toolName: string;
      toolInput: Record<string, unknown>;
      toolUseId: string;
      output?: string;
      isError?: boolean;
    }
  | { role: 'result'; costUsd: number; durationMs: number; numTurns: number; isError: boolean }
  | { role: 'error'; text: string };

type TaskLog = {
  userId: number;
  taskName: string;
  taskDirName: string;
  entryName: string;
  entryType: 'file' | 'directory';
  provider: string;
  model: string;
  startedAt: Date;
  messages: ChatMessage[];
};

type LogEntry = {
  userId: number;
  log: TaskLog;
};

const activeLogs = new Map<string, LogEntry>();
let logCounter = 0;

export function createTaskLog(userId: number, taskInfo: TaskInfo, provider: string, model: string): string {
  const logId = `log_${Date.now()}_${++logCounter}`;

  const log: TaskLog = {
    userId,
    taskName: taskInfo.taskName,
    taskDirName: taskInfo.taskDirName,
    entryName: taskInfo.entryName,
    entryType: taskInfo.entryType,
    provider,
    model,
    startedAt: new Date(),
    messages: [],
  };

  activeLogs.set(logId, { userId, log });
  return logId;
}

export function appendToLog(logId: string, message: ChatMessage) {
  const entry = activeLogs.get(logId);
  if (!entry) return;

  // For tool results, update the existing tool message instead of appending
  if (message.role === 'tool' && message.output !== undefined) {
    const existing = entry.log.messages.find((m) => m.role === 'tool' && m.toolUseId === message.toolUseId);
    if (existing && existing.role === 'tool') {
      existing.output = message.output;
      existing.isError = message.isError;
      return;
    }
  }

  entry.log.messages.push(message);
}

export async function finalizeLog(logId: string) {
  const entry = activeLogs.get(logId);
  if (!entry) return;

  const { log } = entry;
  const lastMessage = log.messages[log.messages.length - 1];
  const isError = lastMessage?.role === 'result' ? lastMessage.isError : lastMessage?.role === 'error';

  try {
    await db.insert(schema.taskLogs).values({
      userId: log.userId,
      taskName: log.taskName,
      taskDirName: log.taskDirName,
      entryName: log.entryName,
      entryType: log.entryType,
      provider: log.provider,
      model: log.model,
      isError: !!isError,
      messages: log.messages,
      startedAt: log.startedAt,
      completedAt: new Date(),
    });
  } catch (err) {
    console.error('[task-logger] Failed to write log:', err);
  }

  activeLogs.delete(logId);
}
