import { shell, type WebContents } from "electron";
import type { LogEntry, TaskRunRequest, TaskRunResult } from "../../shared/types";
import type { SmqjhClient } from "../cloud/smqjhClient";
import type { ConfigStore } from "../config/appConfig";
import type { ReadOnlyDatabaseClient } from "../db/readOnlyDatabase";
import { LogStore } from "./logStore";
import { executeTask } from "./tasks";

export class AgentRunner {
  constructor(
    private readonly deps: {
      client: SmqjhClient;
      database: ReadOnlyDatabaseClient;
      configStore: ConfigStore;
      logStore: LogStore;
      getWebContents: () => WebContents | undefined;
    }
  ) {}

  async run(request: TaskRunRequest): Promise<TaskRunResult> {
    const startedAt = new Date().toISOString();

    try {
      const result = await executeTask(request, {
        client: this.deps.client,
        database: this.deps.database,
        configStore: this.deps.configStore,
        openExternal: (url) => shell.openExternal(url),
        log: (message, context) => this.log("info", message, context)
      });
      const finishedAt = new Date().toISOString();
      const entry = result.success
        ? this.log("success", result.message, { taskId: request.taskId })
        : this.log("error", result.message, { taskId: request.taskId });

      return {
        taskId: request.taskId,
        startedAt,
        finishedAt,
        ...result,
        data: result.data ?? entry.context
      };
    } catch (error) {
      const message = error instanceof Error ? error.message : String(error);
      this.log("error", message, { taskId: request.taskId });
      return {
        taskId: request.taskId,
        success: false,
        message,
        startedAt,
        finishedAt: new Date().toISOString()
      };
    }
  }

  private log(level: LogEntry["level"], message: string, context?: Record<string, unknown>): LogEntry {
    const entry = this.deps.logStore.add(level, message, context);
    this.deps.getWebContents()?.send("logs:entry", entry);
    return entry;
  }
}
