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

/**
 * TreeView provider for displaying registered MCP servers.
 * Groups servers by category for organized browsing.
 */
export class ServersTreeProvider
  implements vscode.TreeDataProvider<ServerTreeItem>
{
  private _onDidChangeTreeData = new vscode.EventEmitter<
    ServerTreeItem | undefined | void
  >();
  readonly onDidChangeTreeData = this._onDidChangeTreeData.event;

  private _servers: ServerInfo[] = [];

  constructor(private readonly _client: BridgeClient) {}

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

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

  async getChildren(element?: ServerTreeItem): Promise<ServerTreeItem[]> {
    if (!element) {
      // Root level -- only show user-installed servers (not the full catalog)
      try {
        this._servers = await this._client.listInstalledServers();
      } catch {
        this._servers = [];
      }

      if (this._servers.length === 0) {
        return [
          new ServerTreeItem(
            "No servers added yet. Install from the Marketplace.",
            vscode.TreeItemCollapsibleState.None,
            "info"
          ),
        ];
      }

      // Group by category
      const categories = new Map<string, ServerInfo[]>();
      for (const server of this._servers) {
        const cat = server.category || "uncategorized";
        if (!categories.has(cat)) {
          categories.set(cat, []);
        }
        categories.get(cat)!.push(server);
      }

      return Array.from(categories.entries())
        .sort(([a], [b]) => a.localeCompare(b))
        .map(
          ([cat, servers]) =>
            new ServerTreeItem(
              `${cat} (${servers.length})`,
              vscode.TreeItemCollapsibleState.Expanded,
              "category",
              undefined,
              cat
            )
        );
    }

    if (element.kind === "category" && element.categoryId) {
      // Category level -- show servers in this category
      const servers = this._servers.filter(
        (s) => (s.category || "uncategorized") === element.categoryId
      );

      return servers.map((s) => {
        const state = s.enabled ? "server-enabled" : "server-disabled";
        const icon = s.enabled
          ? new vscode.ThemeIcon("check", new vscode.ThemeColor("charts.green"))
          : new vscode.ThemeIcon(
              "circle-slash",
              new vscode.ThemeColor("charts.red")
            );

        const item = new ServerTreeItem(
          s.name || s.id,
          vscode.TreeItemCollapsibleState.None,
          state,
          s,
          undefined
        );
        item.iconPath = icon;
        item.description = s.transport;
        item.tooltip = this._buildTooltip(s);
        item.contextValue = state;
        return item;
      });
    }

    return [];
  }

  private _buildTooltip(server: ServerInfo): vscode.MarkdownString {
    const md = new vscode.MarkdownString();
    md.appendMarkdown(`**${server.name || server.id}**\n\n`);
    if (server.description) {
      md.appendMarkdown(`${server.description}\n\n`);
    }
    md.appendMarkdown(`- **ID:** \`${server.id}\`\n`);
    md.appendMarkdown(`- **Transport:** ${server.transport}\n`);
    md.appendMarkdown(`- **Category:** ${server.category}\n`);
    md.appendMarkdown(
      `- **Status:** ${server.enabled ? "Enabled" : "Disabled"}\n`
    );
    if (server.tool_count !== undefined) {
      md.appendMarkdown(`- **Tools:** ${server.tool_count}\n`);
    }
    return md;
  }

  /** Get the server ID from a tree item. */
  getServerId(item: ServerTreeItem): string | undefined {
    return item.serverInfo?.id;
  }
}

export class ServerTreeItem extends vscode.TreeItem {
  constructor(
    label: string,
    collapsibleState: vscode.TreeItemCollapsibleState,
    public readonly kind: string,
    public readonly serverInfo?: ServerInfo,
    public readonly categoryId?: string
  ) {
    super(label, collapsibleState);

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