import * as vscode from "vscode";
import { BridgeClient, InstanceInfo } from "../bridge/client";

/**
 * TreeView provider for displaying active MCP server instances.
 * Shows running instances grouped by server, with tool details.
 */
export class InstancesTreeProvider
  implements vscode.TreeDataProvider<InstanceTreeItem>
{
  private _onDidChangeTreeData = new vscode.EventEmitter<
    InstanceTreeItem | undefined | void
  >();
  readonly onDidChangeTreeData = this._onDidChangeTreeData.event;

  private _instances: InstanceInfo[] = [];

  constructor(private readonly _client: BridgeClient) {}

  refresh(): void {
    this._onDidChangeTreeData.fire();
  }

  getTreeItem(element: InstanceTreeItem): vscode.TreeItem {
    return element;
  }

  async getChildren(element?: InstanceTreeItem): Promise<InstanceTreeItem[]> {
    if (!element) {
      // Root level -- show instances grouped by server
      try {
        this._instances = await this._client.listInstances();
      } catch {
        this._instances = [];
      }

      if (this._instances.length === 0) {
        return [
          new InstanceTreeItem(
            "No active instances",
            vscode.TreeItemCollapsibleState.None,
            "info"
          ),
        ];
      }

      // Group by server_id
      const groups = new Map<string, InstanceInfo[]>();
      for (const inst of this._instances) {
        if (!groups.has(inst.server_id)) {
          groups.set(inst.server_id, []);
        }
        groups.get(inst.server_id)!.push(inst);
      }

      return Array.from(groups.entries()).map(([serverId, instances]) => {
        const item = new InstanceTreeItem(
          `${serverId} (${instances.length})`,
          vscode.TreeItemCollapsibleState.Expanded,
          "server-group",
          undefined,
          serverId
        );
        item.iconPath = new vscode.ThemeIcon(
          "server-process",
          new vscode.ThemeColor("charts.blue")
        );
        return item;
      });
    }

    if (element.kind === "server-group" && element.serverId) {
      const instances = this._instances.filter(
        (i) => i.server_id === element.serverId
      );
      return instances.map((inst) => {
        const stateIcon = this._getStateIcon(inst.state);
        const item = new InstanceTreeItem(
          inst.instance_id.substring(0, 8),
          inst.tools.length > 0
            ? vscode.TreeItemCollapsibleState.Collapsed
            : vscode.TreeItemCollapsibleState.None,
          "instance",
          inst
        );
        item.iconPath = stateIcon;
        item.description = `${inst.state} | ${inst.total_tool_calls} calls`;
        item.tooltip = this._buildTooltip(inst);
        item.contextValue = "instance";
        return item;
      });
    }

    if (element.kind === "instance" && element.instanceInfo?.tools) {
      return element.instanceInfo.tools.map((tool) => {
        const toolName = typeof tool === "string" ? tool : (tool.name || "unknown");
        const toolDesc = typeof tool === "string" ? "" : (tool.description || "");
        const item = new InstanceTreeItem(
          toolName,
          vscode.TreeItemCollapsibleState.None,
          "tool"
        );
        item.iconPath = new vscode.ThemeIcon("symbol-method");
        if (toolDesc) {
          item.tooltip = toolDesc;
          item.description = toolDesc.length > 50 ? toolDesc.substring(0, 50) + "..." : toolDesc;
        }
        return item;
      });
    }

    return [];
  }

  private _getStateIcon(state: string): vscode.ThemeIcon {
    switch (state) {
      case "active":
      case "running":
        return new vscode.ThemeIcon(
          "play",
          new vscode.ThemeColor("charts.green")
        );
      case "starting":
      case "connecting":
        return new vscode.ThemeIcon(
          "loading~spin",
          new vscode.ThemeColor("charts.yellow")
        );
      case "error":
      case "failed":
        return new vscode.ThemeIcon(
          "error",
          new vscode.ThemeColor("charts.red")
        );
      default:
        return new vscode.ThemeIcon("circle-outline");
    }
  }

  private _buildTooltip(inst: InstanceInfo): vscode.MarkdownString {
    const md = new vscode.MarkdownString();
    md.appendMarkdown(`**Instance:** \`${inst.instance_id}\`\n\n`);
    md.appendMarkdown(`- **Server:** ${inst.server_id}\n`);
    md.appendMarkdown(`- **State:** ${inst.state}\n`);
    md.appendMarkdown(`- **Created:** ${inst.created_at}\n`);
    md.appendMarkdown(`- **Tool Calls:** ${inst.total_tool_calls}\n`);
    md.appendMarkdown(`- **Errors:** ${inst.total_errors}\n`);
    if (inst.tools.length > 0) {
      const toolNames = inst.tools.map((t) =>
        typeof t === "string" ? t : (t.name || "?")
      );
      md.appendMarkdown(`- **Tools:** ${toolNames.join(", ")}\n`);
    }
    return md;
  }

  /** Get instance ID from a tree item. */
  getInstanceId(item: InstanceTreeItem): string | undefined {
    return item.instanceInfo?.instance_id;
  }
}

export class InstanceTreeItem extends vscode.TreeItem {
  constructor(
    label: string,
    collapsibleState: vscode.TreeItemCollapsibleState,
    public readonly kind: string,
    public readonly instanceInfo?: InstanceInfo,
    public readonly serverId?: string
  ) {
    super(label, collapsibleState);

    if (kind === "info") {
      this.iconPath = new vscode.ThemeIcon("info");
    }
  }
}
