import { mkdir, rm, writeFile } from "node:fs/promises";
import path from "node:path";
import { AppConfigService } from "../../apps/desktop/src/main/services/app-config.js";
import { loadBootstrapExpertPrompt } from "../../apps/desktop/src/main/services/bootstrap-expert-prompts.js";
import { ProjectContextService } from "../../apps/desktop/src/main/services/project-context.js";
import { ProjectExecutionRouter } from "../../apps/desktop/src/main/services/project-execution-router.js";
import { ProjectStoreService } from "../../apps/desktop/src/main/services/project-store.js";
import type { SystemSummary } from "../../packages/shared-types/src/index.js";

function assert(condition: unknown, message: string): asserts condition {
  if (!condition) {
    throw new Error(message);
  }
}

function buildSystemSummary(repoRoot: string, userDataPath: string, logsPath: string): SystemSummary {
  return {
    appName: "千匠问天",
    appVersion: "0.1.0-smoke",
    isPackaged: false,
    platform: process.platform,
    arch: process.arch,
    appPath: path.join(repoRoot, "apps", "desktop"),
    resourcesPath: path.join(repoRoot, "apps", "desktop"),
    userDataPath,
    logsPath
  };
}

async function main(): Promise<void> {
  const repoRoot = process.cwd();
  const resultPath = path.resolve(process.argv[2] ?? path.join(repoRoot, ".tmp", "expert-bootstrap-prompt-smoke", "result.json"));
  const tempRoot = path.dirname(resultPath);
  const userDataPath = path.join(tempRoot, "user-data");
  const logsPath = path.join(tempRoot, "logs");

  await rm(tempRoot, { recursive: true, force: true });
  await mkdir(userDataPath, { recursive: true });
  await mkdir(logsPath, { recursive: true });

  const configService = new AppConfigService(userDataPath);
  await configService.load();

  const projectStore = new ProjectStoreService(configService);
  await projectStore.initialize();
  const projectContextService = new ProjectContextService(projectStore);
  const systemSummary = buildSystemSummary(repoRoot, userDataPath, logsPath);
  const projectExecutionRouter = new ProjectExecutionRouter(systemSummary);

  const scenarios = [
    {
      projectId: "content-account-planning",
      projectName: "Content Account Planning Expert",
      prompt: "帮我规划一个母婴账号的人设、栏目和更新节奏。"
    },
    {
      projectId: "zhihu",
      projectName: "Zhihu Expert",
      prompt: "帮我写一个知乎回答开头，主题是副业转型。"
    }
  ] as const;

  const results: Array<Record<string, unknown>> = [];

  for (const scenario of scenarios) {
    const promptText = await loadBootstrapExpertPrompt(systemSummary, scenario.projectId);
    assert(promptText, `Bootstrap expert prompt was not found for ${scenario.projectId}.`);

    const project = await projectStore.upsertProject({
      id: scenario.projectId,
      name: scenario.projectName,
      description: `Smoke fixture for ${scenario.projectId}.`,
      ready: true,
      boundSkillIds: []
    });
    const projectRoot = await projectStore.getProjectRoot(project.id);
    await writeFile(path.join(projectRoot, "README.md"), `# ${scenario.projectName}\n\nSmoke README for ${scenario.projectId}.\n`, "utf8");
    const session = await projectStore.createSession(`${scenario.projectName} Smoke`, project.id);
    const snapshot = await projectContextService.getSnapshot(project.id);

    const decision = await projectExecutionRouter.decide({
      sessionId: session.id,
      projectId: project.id,
      projectRoot,
      userPrompt: scenario.prompt,
      context: snapshot,
      selectedSkillId: null,
      projectConfig: await projectStore.getProjectPackageConfig(project.id)
    });

    assert(decision.kind === "chat-fallback", `${scenario.projectId} should route through chat-fallback in this smoke fixture.`);
    assert(decision.preparedPrompt.includes("[expert prompt]"), `${scenario.projectId} preparedPrompt did not include the expert prompt section marker.`);
    assert(decision.preparedPrompt.includes(promptText), `${scenario.projectId} preparedPrompt did not include the bootstrap expert prompt body.`);
    assert(decision.preparedPrompt.includes(scenario.prompt), `${scenario.projectId} preparedPrompt did not preserve the user prompt.`);
    assert(decision.preparedPrompt.includes(`Current project: ${project.name} (${project.id})`), `${scenario.projectId} preparedPrompt did not include the project identity.`);

    results.push({
      projectId: project.id,
      decisionKind: decision.kind,
      promptLoaded: true,
      preparedPromptIncludesExpertSection: decision.preparedPrompt.includes("[expert prompt]"),
      preparedPromptIncludesBootstrapPrompt: decision.preparedPrompt.includes(promptText),
      preparedPromptIncludesUserPrompt: decision.preparedPrompt.includes(scenario.prompt)
    });
  }

  const ordinaryProject = await projectStore.upsertProject({
    id: "generic-smoke",
    name: "Generic Smoke",
    description: "Control project without standalone expert bootstrap prompt.",
    ready: true,
    boundSkillIds: []
  });
  const ordinaryProjectRoot = await projectStore.getProjectRoot(ordinaryProject.id);
  const ordinarySession = await projectStore.createSession("Generic Smoke", ordinaryProject.id);
  const ordinarySnapshot = await projectContextService.getSnapshot(ordinaryProject.id);
  const ordinaryDecision = await projectExecutionRouter.decide({
    sessionId: ordinarySession.id,
    projectId: ordinaryProject.id,
    projectRoot: ordinaryProjectRoot,
    userPrompt: "普通项目的默认对话",
    context: ordinarySnapshot,
    selectedSkillId: null,
    projectConfig: await projectStore.getProjectPackageConfig(ordinaryProject.id)
  });

  assert(!ordinaryDecision.preparedPrompt.includes("[expert prompt]"), "Non-expert project unexpectedly included expert prompt content.");

  const summary = {
    ok: true,
    userDataPath,
    logsPath,
    results,
    controlProjectId: ordinaryProject.id,
    controlPreparedPromptIncludesExpertSection: ordinaryDecision.preparedPrompt.includes("[expert prompt]")
  };

  await mkdir(path.dirname(resultPath), { recursive: true });
  await writeFile(resultPath, JSON.stringify(summary, null, 2), "utf8");
  console.log(JSON.stringify(summary, null, 2));
}

main().catch(async (error) => {
  const repoRoot = process.cwd();
  const resultPath = path.resolve(process.argv[2] ?? path.join(repoRoot, ".tmp", "expert-bootstrap-prompt-smoke", "result.json"));
  const failure = {
    ok: false,
    error: error instanceof Error ? error.stack ?? error.message : String(error)
  };

  await mkdir(path.dirname(resultPath), { recursive: true });
  await writeFile(resultPath, JSON.stringify(failure, null, 2), "utf8");
  console.error(failure.error);
  process.exitCode = 1;
});
