import * as vscode from "vscode"
import type { KiloClient } from "@kilocode/sdk/v2/client"
import type { KiloConnectionService } from "../cli-backend"

type BrowserAutomationState = "disabled" | "registering" | "connected" | "failed" | "disconnected"

export class BrowserAutomationService implements vscode.Disposable {
  private state: BrowserAutomationState = "disabled"
  private disposables: vscode.Disposable[] = []

  // MCP server name used when registering with the CLI backend
  private static readonly MCP_SERVER_NAME = "kilo-playwright"

  constructor(private readonly connectionService: KiloConnectionService) {
    // Listen for settings changes
    this.disposables.push(
      vscode.workspace.onDidChangeConfiguration((e) => {
        if (e.affectsConfiguration("kilo-code.new.browserAutomation")) {
          this.syncWithSettings()
        }
      }),
    )
  }

  /**
   * Read settings and enable/disable accordingly.
   * Called on construction and when settings change.
   */
  async syncWithSettings(): Promise<void> {
    const config = vscode.workspace.getConfiguration("kilo-code.new.browserAutomation")
    const enabled = config.get<boolean>("enabled", false)

    if (enabled) {
      await this.register()
    } else {
      await this.unregister()
    }
  }

  /**
   * Re-register the MCP server after CLI backend reconnects.
   * Should be called from the connection state change handler.
   */
  async reregisterIfEnabled(): Promise<void> {
    const config = vscode.workspace.getConfiguration("kilo-code.new.browserAutomation")
    const enabled = config.get<boolean>("enabled", false)
    if (enabled) {
      await this.register()
    }
  }

  /**
   * Register the Playwright MCP server with the CLI backend.
   */
  private async register(): Promise<void> {
    this.setState("registering")

    const client = this.getClient()
    if (!client) {
      console.error("[Kilo New] BrowserAutomationService: No SDK client available")
      this.setState("failed")
      return
    }

    const config = vscode.workspace.getConfiguration("kilo-code.new.browserAutomation")
    const useSystemChrome = config.get<boolean>("useSystemChrome", true)
    const headless = config.get<boolean>("headless", false)

    // Build the command for the Playwright MCP server
    const command = ["npx", "@playwright/mcp@latest"]
    if (headless) {
      command.push("--headless")
    }
    if (useSystemChrome) {
      command.push("--browser", "chrome")
    }

    try {
      const directory = this.getWorkspaceDirectory()
      const { data: status } = await client.mcp.add(
        {
          name: BrowserAutomationService.MCP_SERVER_NAME,
          config: {
            type: "local",
            command,
            enabled: true,
            timeout: 60000,
          },
          directory,
        },
        { throwOnError: true },
      )

      const serverStatus = status[BrowserAutomationService.MCP_SERVER_NAME]
      if (serverStatus?.status === "connected") {
        this.setState("connected")
      } else if (serverStatus?.status === "failed") {
        console.error(
          "[Kilo New] BrowserAutomationService: MCP server failed:",
          (serverStatus as { error?: string }).error,
        )
        this.setState("failed")
      } else {
        this.setState("disconnected")
      }
    } catch (error) {
      console.error("[Kilo New] BrowserAutomationService: Failed to register MCP server:", error)
      this.setState("failed")
    }
  }

  /**
   * Unregister/disconnect the Playwright MCP server.
   */
  private async unregister(): Promise<void> {
    if (this.state === "disabled") {
      return
    }

    const client = this.getClient()
    if (client) {
      try {
        const directory = this.getWorkspaceDirectory()
        await client.mcp.disconnect(
          { name: BrowserAutomationService.MCP_SERVER_NAME, directory },
          { throwOnError: true },
        )
      } catch (error) {
        console.error("[Kilo New] BrowserAutomationService: Failed to disconnect MCP server:", error)
      }
    }

    this.setState("disabled")
  }

  private getClient(): KiloClient | null {
    try {
      return this.connectionService.getClient()
    } catch {
      return null
    }
  }

  private getWorkspaceDirectory(): string {
    const folders = vscode.workspace.workspaceFolders
    if (folders && folders.length > 0) {
      return folders[0].uri.fsPath
    }
    return process.cwd()
  }

  private setState(state: BrowserAutomationState): void {
    if (this.state === state) {
      return
    }
    console.log(`[Kilo New] BrowserAutomationService: State ${this.state} → ${state}`)
    this.state = state
  }

  dispose(): void {
    for (const d of this.disposables) {
      d.dispose()
    }
    this.disposables = []
  }
}
