import { readFile, stat } from "node:fs/promises";
import path from "node:path";
import type {
  ProjectContextSnapshot,
  ProjectExecutionDecision,
  ProjectExecutionRequest,
  ProjectPackageConfig,
  SystemSummary
} from "@qjclaw/shared-types";
import { loadBootstrapExpertPrompt } from "./bootstrap-expert-prompts.js";
import { isPublishIntentPrompt } from "./project-prompt-signals.js";

const WORKSPACE_ENTRY_MARKERS = ["AGENT", "AGENT.md", "AGENTS.md"];
const LEGACY_WORKSPACE_PLUGIN_MARKERS = [
  path.join("plugin", "openclaw.plugin.json"),
  path.join("plugin", "index.js"),
  path.join("plugin", "index.ts")
] as const;

async function pathExists(targetPath: string): Promise<boolean> {
  try {
    await stat(targetPath);
    return true;
  } catch {
    return false;
  }
}

function renderSystemContext(snapshot: ProjectContextSnapshot, expertPrompt?: string | null): string {
  const sections: string[] = [
    "You are operating inside a desktop project-isolated workspace.",
    `Current project: ${snapshot.projectName} (${snapshot.projectId})`,
    `Project root: ${snapshot.projectRoot}`
  ];

  if (expertPrompt) {
    sections.push(["[expert prompt]", expertPrompt].join("\n"));
  }
  if (snapshot.boundSkills.length > 0) {
    sections.push([
      "Available project skills:",
      ...snapshot.boundSkills.map((skill) => `- ${skill.name} (${skill.id})${skill.description ? `: ${skill.description}` : ""}`)
    ].join("\n"));
  }
  if (snapshot.soul) {
    sections.push(["[SOUL.md]", snapshot.soul].join("\n"));
  }
  if (snapshot.user) {
    sections.push(["[USER.md]", snapshot.user].join("\n"));
  }
  if (snapshot.memorySummary) {
    sections.push(["[memory summary]", snapshot.memorySummary].join("\n"));
  }
  if (snapshot.readme) {
    sections.push(["[README.md]", snapshot.readme].join("\n"));
  }

  sections.push("Keep project context isolated to this project and session.");
  return sections.join("\n\n");
}

async function buildPreparedPrompt(
  systemSummary: SystemSummary,
  snapshot: ProjectContextSnapshot,
  userPrompt: string
): Promise<string> {
  const expertPrompt = await loadBootstrapExpertPrompt(systemSummary, snapshot.projectId);
  return [
    renderSystemContext(snapshot, expertPrompt),
    "User request:",
    userPrompt
  ].join("\n\n");
}

function resolveDeclaredWorkspaceEntry(projectConfig?: ProjectPackageConfig | null): string | null {
  if (projectConfig?.defaultEntry?.type === "workspace-entry") {
    return `project default entry ${projectConfig.defaultEntry.id}`;
  }
  const explicitWorkspaceEntry = projectConfig?.entries.find((entry) => entry.type === "workspace-entry");
  return explicitWorkspaceEntry ? `project entry ${explicitWorkspaceEntry.id}` : null;
}

export class ProjectExecutionRouter {
  constructor(private readonly systemSummary: SystemSummary) {}

  async decide(request: ProjectExecutionRequest): Promise<ProjectExecutionDecision> {
    const preparedPrompt = await buildPreparedPrompt(this.systemSummary, request.context, request.userPrompt);
    const declaredWorkspaceEntryReason = resolveDeclaredWorkspaceEntry(request.projectConfig);
    if (declaredWorkspaceEntryReason && (!request.selectedSkillId || isPublishIntentPrompt(request.userPrompt))) {
      return {
        kind: "workspace-entry",
        projectRoot: request.projectRoot,
        preparedPrompt,
        reason: declaredWorkspaceEntryReason
      };
    }

    const workspaceEntryReason = await this.detectWorkspaceEntry(request.projectRoot);
    if (workspaceEntryReason && (!request.selectedSkillId || isPublishIntentPrompt(request.userPrompt))) {
      return {
        kind: "workspace-entry",
        projectRoot: request.projectRoot,
        preparedPrompt,
        reason: workspaceEntryReason
      };
    }

    const legacyWorkspaceEntryReason = await this.detectLegacyWorkspaceEntry(request.projectRoot);
    if (legacyWorkspaceEntryReason && isPublishIntentPrompt(request.userPrompt)) {
      return {
        kind: "workspace-entry",
        projectRoot: request.projectRoot,
        preparedPrompt,
        reason: legacyWorkspaceEntryReason
      };
    }

    if (request.selectedSkillId) {
      return {
        kind: "skill",
        skillId: request.selectedSkillId,
        preparedPrompt
      };
    }

    return {
      kind: "chat-fallback",
      preparedPrompt
    };
  }

  private async detectWorkspaceEntry(projectRoot: string): Promise<string | null> {
    const projectJsonPath = path.join(projectRoot, "project.json");
    try {
      const raw = await readFile(projectJsonPath, "utf8");
      const projectConfig = JSON.parse(raw) as Record<string, unknown>;
      const declaredEntry = ["workspaceEntry", "executionEntry", "workspace_entry"]
        .map((key) => projectConfig[key])
        .find((value) => typeof value === "string" && value.trim().length > 0);
      if (typeof declaredEntry === "string") {
        return `project.json declares workspace entry ${declaredEntry.trim()}`;
      }
      const enabledFlag = ["workspaceEntryEnabled", "executionEntryEnabled"]
        .map((key) => projectConfig[key])
        .find((value) => typeof value === "boolean");
      if (enabledFlag === true) {
        return "project.json enables workspace entry";
      }
    } catch {
      // Ignore project.json parse failures here and continue with marker files.
    }

    for (const marker of WORKSPACE_ENTRY_MARKERS) {
      if (await pathExists(path.join(projectRoot, marker))) {
        return `workspace marker ${marker} detected`;
      }
    }

    return null;
  }

  private async detectLegacyWorkspaceEntry(projectRoot: string): Promise<string | null> {
    for (const marker of LEGACY_WORKSPACE_PLUGIN_MARKERS) {
      if (await pathExists(path.join(projectRoot, marker))) {
        return `legacy workspace plugin marker ${marker} detected`;
      }
    }

    return null;
  }
}
