import * as vscode from "vscode";
import type {
  PythonExtension,
  ResolvedEnvironment,
} from "@vscode/python-extension";
import { PYTHON_EXTENSION_ID } from "../constants";
import type { ErrorWebviewConfig } from "../types";
import { Logger } from "../utils";
import { join } from "path";
import { existsSync } from "fs";
import { getRootWorkspaceFolder } from "../utils/rootWorkspace";
import type { ConfigService } from "./configService";
import { ConfigKey } from "./configService";

interface ExtensionDependencies {
  pythonPath?: string;
  errorConfig?: ErrorWebviewConfig;
}

export const codeflashInitErrorConfig = {
  icon: "warning",
  title: "Codeflash is installed but not properly initialized",
  details: "Please run codeflash init to initialize Codeflash",
  terminalCommand: "codeflash init",
};

export class PythonService {
  logger = new Logger("pythonService");
  private reloadOnInterpreterChange: boolean = false;
  constructor(private readonly configService: ConfigService) {}

  setReloadOnInterpreterChange(reload: boolean) {
    this.reloadOnInterpreterChange = reload;
  }
  async validateDependencies(): Promise<ExtensionDependencies> {
    // TODO: for now we try to find the nearest python venv in the current workspace folder
    // later we can have a settings
    // if (process.platform !== "win32") {
    //   const nearestPythonPath = await this.tryGetTheClosestPythonVenv();
    //   if (nearestPythonPath) {
    //     return {
    //       pythonPath: nearestPythonPath,
    //     };
    //   }
    // }

    // codeflash uses python extension as a required dependency, so we can be sure the ms-python.python extension is installed and activated
    let pythonExtension =
      vscode.extensions.getExtension<PythonExtension>(PYTHON_EXTENSION_ID)!;
    const exports = pythonExtension.exports;
    const activeEnvironment: ResolvedEnvironment | undefined =
      await exports.environments.resolveEnvironment(
        exports.environments.getActiveEnvironmentPath(),
      );

    if (!activeEnvironment?.executable?.uri) {
      return {
        errorConfig: {
          icon: "error",
          title: "No Python Environment Found",
          details: "Please install Python and ensure it's in your PATH.",
        },
      };
    }

    const pythonPath = activeEnvironment.executable.uri.fsPath;

    // check for codeflash lsp module
    // try {
    //   execSync(`${pythonPath} -c "import ${LSP_MODULE_NAME}"`, {
    //     env: { CODEFLASH_LSP: "true" },
    //   });
    // } catch (error) {
    //   const msg = error instanceof Error ? error.message : String(error);
    //   const match = msg.match(/ModuleNotFoundError:.*\n?/);
    //   const errorMsg = match ? match[0].trim() : msg.trim();

    //   return {
    //     errorConfig: {
    //       icon: "warning",
    //       title: "Codeflash LSP Module Not Found",
    //       details: `${errorMsg}<br/><br/> Active Python: ${pythonPath}`,
    //       terminalCommand: `pip install --upgrade codeflash`,
    //     },
    //   };
    // }

    return {
      pythonPath,
    };
  }

  // private async tryGetTheClosestPythonVenv(): Promise<string | undefined> {
  //   const possibleVenvs = [".venv", "venv", "my-venv"];
  //   const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
  //   if (!workspaceFolder) {
  //     return;
  //   }
  //   const workspacePath = workspaceFolder.uri.fsPath;
  //   for (const venv of possibleVenvs) {
  //     const venvPath = join(workspacePath, venv, "bin", "python");
  //     try {
  //       await vscode.workspace.fs.stat(vscode.Uri.file(venvPath));
  //       return venvPath;
  //     } catch {
  //     }
  //   }
  //   return;
  // }

  public getPackageManager(
    root?: string,
  ): "uv" | "poetry" | "pipenv" | "conda" | "pip" {
    const workspaceFolder = getRootWorkspaceFolder();
    const finalRoot = root ?? workspaceFolder?.uri.fsPath;

    if (!finalRoot) {
      return "pip";
    }

    // Check for UV
    if (existsSync(join(finalRoot, "uv.lock"))) {
      return "uv";
    }

    // Check for Poetry
    if (existsSync(join(finalRoot, "poetry.lock"))) {
      return "poetry";
    }

    // Check for Pipenv
    if (existsSync(join(finalRoot, "Pipfile.lock"))) {
      return "pipenv";
    }

    // Check for Conda environment
    if (
      existsSync(join(finalRoot, "environment.yml")) ||
      existsSync(join(finalRoot, "environment.yaml"))
    ) {
      return "conda";
    }

    return "pip";
  }

  public getInstallCommand(
    pythonPath: string,
    packageManager: "uv" | "poetry" | "pipenv" | "conda" | "pip",
    upgrade: boolean = false,
  ): string {
    const upgradeFlag = upgrade ? "--upgrade " : "";
    switch (packageManager) {
      case "uv":
        return upgrade
          ? "uv pip install --upgrade codeflash"
          : "uv add codeflash";
      case "poetry":
        return "poetry add codeflash";
      case "pipenv":
        return "pipenv install codeflash";
      case "conda":
        return "pip install codeflash";
      case "pip":
      default:
        const quotedPath = pythonPath.includes(" ")
          ? `"${pythonPath}"`
          : pythonPath;
        return `${quotedPath} -m pip install ${upgradeFlag}codeflash`.trim();
    }
  }

  public setupInterpreterWatcher(): vscode.Disposable {
    const pythonExtension =
      vscode.extensions.getExtension<PythonExtension>(PYTHON_EXTENSION_ID)!;
    const exports = pythonExtension.exports;
    const interpreterWatcher =
      exports.environments.onDidChangeActiveEnvironmentPath(() => {
        const configuredPath = this.configService.get(
          ConfigKey.DefaultInterpreterPath,
        ) as string | null;
        if (configuredPath) {
          // user has a configured path, don't override it
          return;
        }

        // used interpreter changed
        if (this.reloadOnInterpreterChange) {
          vscode.commands.executeCommand("codeflash.reloadExtension");
        }
      });

    return interpreterWatcher;
  }
}
