import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import * as fs from "fs";
import * as path from "path";
import { logger } from "../core/monitoring/logger.js";
const SPEC_DIR = "docs/specs";
const SPEC_CONFIGS = {
  "one-pager": {
    filename: "ONE_PAGER.md",
    title: "One-Pager",
    sections: [
      "Problem",
      "Audience",
      "Platform",
      "Core Flow",
      "MVP Features",
      "Non-Goals",
      "Metrics"
    ],
    inputs: []
  },
  "dev-spec": {
    filename: "DEV_SPEC.md",
    title: "Development Specification",
    sections: [
      "Architecture",
      "Tech Stack",
      "API Contracts",
      "Data Models",
      "Auth",
      "Error Handling",
      "Deployment"
    ],
    inputs: ["one-pager"]
  },
  "prompt-plan": {
    filename: "PROMPT_PLAN.md",
    title: "Prompt Plan",
    sections: [
      "Stage A: Project Setup",
      "Stage B: Core Data Models",
      "Stage C: API Layer",
      "Stage D: Business Logic",
      "Stage E: Frontend / UI",
      "Stage F: Integration & Testing",
      "Stage G: Deploy & Polish"
    ],
    inputs: ["one-pager", "dev-spec"]
  },
  agents: {
    filename: "AGENTS.md",
    title: "AGENTS.md",
    sections: [
      "Repo Files",
      "Responsibilities",
      "Guardrails",
      "Testing",
      "When to Ask"
    ],
    inputs: ["one-pager", "dev-spec", "prompt-plan"]
  }
};
function onePagerTemplate(title) {
  return `# ${title} \u2014 One-Pager

## Problem
<!-- What problem does this solve? Who has this problem? -->

## Audience
<!-- Primary users and their context -->

## Platform
<!-- Web / Mobile / CLI / API \u2014 and why -->

## Core Flow
<!-- Happy-path user journey in 3-5 steps -->
1.
2.
3.

## MVP Features
<!-- Minimum set of features for first release -->
- [ ]
- [ ]
- [ ]

## Non-Goals
<!-- Explicitly out of scope for MVP -->
-

## Metrics
<!-- How will you measure success? -->
-
`;
}
function devSpecTemplate(title, onePagerContent) {
  return `# ${title} \u2014 Development Specification

> Generated from ONE_PAGER.md

<details><summary>Source: ONE_PAGER.md</summary>

${onePagerContent}

</details>

## Architecture
<!-- High-level system diagram / component breakdown -->

## Tech Stack
<!-- Languages, frameworks, databases, infra -->
| Layer | Choice | Rationale |
|-------|--------|-----------|
| Frontend | | |
| Backend | | |
| Database | | |
| Hosting | | |

## API Contracts
<!-- Key endpoints with request/response shapes -->

## Data Models
<!-- Core entities and relationships -->

## Auth
<!-- Authentication and authorization strategy -->

## Error Handling
<!-- Error codes, retry strategies, user-facing messages -->

## Deployment
<!-- CI/CD, environments, rollback strategy -->
`;
}
function promptPlanTemplate(title, onePagerContent, devSpecContent) {
  return `# ${title} \u2014 Prompt Plan

> Generated from ONE_PAGER.md and DEV_SPEC.md
> Each stage has TDD checkboxes \u2014 check off as tasks complete.

<details><summary>Source: ONE_PAGER.md</summary>

${onePagerContent}

</details>

<details><summary>Source: DEV_SPEC.md</summary>

${devSpecContent}

</details>

## Stage A: Project Setup
- [ ] Initialize repository and tooling
- [ ] Configure CI/CD pipeline
- [ ] Set up development environment

## Stage B: Core Data Models
- [ ] Define database schema
- [ ] Create model layer
- [ ] Write model tests

## Stage C: API Layer
- [ ] Implement API endpoints
- [ ] Add input validation
- [ ] Write API tests

## Stage D: Business Logic
- [ ] Implement core business rules
- [ ] Add edge case handling
- [ ] Write integration tests

## Stage E: Frontend / UI
- [ ] Build core UI components
- [ ] Implement user flows
- [ ] Write UI tests

## Stage F: Integration & Testing
- [ ] End-to-end test suite
- [ ] Performance testing
- [ ] Security audit

## Stage G: Deploy & Polish
- [ ] Production deployment
- [ ] Monitoring and alerting
- [ ] Documentation
`;
}
function agentsTemplate(title, inputs) {
  const sourceBlocks = Object.entries(inputs).map(
    ([name, content]) => `<details><summary>Source: ${name}</summary>

${content}

</details>`
  ).join("\n\n");
  return `# ${title} \u2014 AGENTS.md

> Auto-generated agent configuration for Claude Code / Cursor / Windsurf.

${sourceBlocks}

## Repo Files
<!-- Key files and their purpose -->
| File | Purpose |
|------|---------|
| | |

## Responsibilities
<!-- What this agent should and shouldn't do -->
### DO
-

### DON'T
-

## Guardrails
<!-- Safety constraints and limits -->
- Never commit secrets or credentials
- Always run tests before committing
- Keep changes focused and atomic

## Testing
<!-- How to validate changes -->
\`\`\`bash
npm test
npm run lint
npm run build
\`\`\`

## When to Ask
<!-- Situations where the agent should ask for human input -->
- Architectural changes affecting multiple systems
- Security-sensitive modifications
- Breaking API changes
- Ambiguous requirements
`;
}
class SpecGeneratorSkill {
  constructor(context) {
    this.context = context;
    this.baseDir = process.cwd();
  }
  baseDir;
  /** Generate a spec document by type */
  async generate(type, title, opts) {
    const config = SPEC_CONFIGS[type];
    if (!config) {
      return { success: false, message: `Unknown spec type: ${type}` };
    }
    const specDir = path.join(this.baseDir, SPEC_DIR);
    const outputPath = path.join(specDir, config.filename);
    if (fs.existsSync(outputPath) && !opts?.force) {
      return {
        success: false,
        message: `${config.filename} already exists. Use --force to overwrite.`,
        data: { path: outputPath }
      };
    }
    const inputContents = {};
    for (const inputType of config.inputs) {
      const inputConfig = SPEC_CONFIGS[inputType];
      const inputPath = path.join(specDir, inputConfig.filename);
      if (fs.existsSync(inputPath)) {
        inputContents[inputConfig.filename] = fs.readFileSync(
          inputPath,
          "utf-8"
        );
      }
    }
    const content = this.renderTemplate(type, title, inputContents);
    fs.mkdirSync(specDir, { recursive: true });
    fs.writeFileSync(outputPath, content, "utf-8");
    logger.info(`Generated spec: ${config.filename}`, { type, title });
    return {
      success: true,
      message: `Created ${config.filename}`,
      data: {
        path: outputPath,
        type,
        sections: config.sections,
        inputsUsed: Object.keys(inputContents)
      },
      action: `Generated ${SPEC_DIR}/${config.filename}`
    };
  }
  /** List existing spec documents */
  async list() {
    const specDir = path.join(this.baseDir, SPEC_DIR);
    const specs = [];
    for (const [type, config] of Object.entries(SPEC_CONFIGS)) {
      const filePath = path.join(specDir, config.filename);
      specs.push({
        type,
        filename: config.filename,
        exists: fs.existsSync(filePath),
        path: filePath
      });
    }
    const existing = specs.filter((s) => s.exists);
    const missing = specs.filter((s) => !s.exists);
    return {
      success: true,
      message: `${existing.length}/${specs.length} specs exist`,
      data: { specs, existing, missing }
    };
  }
  /** Update a spec — primarily for checking off PROMPT_PLAN items */
  async update(filePath, changes) {
    const resolvedPath = path.isAbsolute(filePath) ? filePath : path.join(this.baseDir, filePath);
    if (!fs.existsSync(resolvedPath)) {
      return { success: false, message: `File not found: ${resolvedPath}` };
    }
    let content = fs.readFileSync(resolvedPath, "utf-8");
    const checkboxPattern = /^(Stage [A-G])(?::(\d+))?$/;
    const match = changes.match(checkboxPattern);
    if (match) {
      const [, stageName, itemNum] = match;
      content = this.checkItem(
        content,
        stageName,
        itemNum ? parseInt(itemNum) : void 0
      );
    } else {
      const escaped = changes.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
      const re = new RegExp(`- \\[ \\] ${escaped}`, "i");
      if (re.test(content)) {
        content = content.replace(re, `- [x] ${changes}`);
      } else {
        return {
          success: false,
          message: `No unchecked item matching "${changes}" found`
        };
      }
    }
    const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
    const changelog = `
<!-- Updated: ${timestamp} | ${changes} -->
`;
    content += changelog;
    fs.writeFileSync(resolvedPath, content, "utf-8");
    logger.info("Updated spec", { path: resolvedPath, changes });
    return {
      success: true,
      message: `Updated: ${changes}`,
      data: { path: resolvedPath, changes },
      action: `Checked off item in ${path.basename(resolvedPath)}`
    };
  }
  /** Validate completeness of a spec */
  async validate(filePath) {
    const resolvedPath = path.isAbsolute(filePath) ? filePath : path.join(this.baseDir, filePath);
    if (!fs.existsSync(resolvedPath)) {
      return { success: false, message: `File not found: ${resolvedPath}` };
    }
    const content = fs.readFileSync(resolvedPath, "utf-8");
    const unchecked = (content.match(/- \[ \]/g) || []).length;
    const checked = (content.match(/- \[x\]/gi) || []).length;
    const total = checked + unchecked;
    const emptySections = [];
    const sectionRegex = /^## (.+)$/gm;
    let sectionMatch;
    while ((sectionMatch = sectionRegex.exec(content)) !== null) {
      const sectionName = sectionMatch[1];
      const sectionStart = content.indexOf(sectionMatch[0]);
      const nextSection = content.indexOf("\n## ", sectionStart + 1);
      const sectionContent = nextSection === -1 ? content.slice(sectionStart + sectionMatch[0].length) : content.slice(sectionStart + sectionMatch[0].length, nextSection);
      const stripped = sectionContent.replace(/<!--.*?-->/gs, "").replace(/\s+/g, "").trim();
      if (stripped.length === 0 || stripped === "||") {
        emptySections.push(sectionName);
      }
    }
    const isComplete = unchecked === 0 && emptySections.length === 0;
    return {
      success: true,
      message: isComplete ? "Spec is complete" : `Spec incomplete: ${unchecked} unchecked items, ${emptySections.length} empty sections`,
      data: {
        path: resolvedPath,
        checkboxes: { checked, unchecked, total },
        emptySections,
        isComplete,
        completionPercent: total > 0 ? Math.round(checked / total * 100) : 100
      }
    };
  }
  // --- Private helpers ---
  renderTemplate(type, title, inputs) {
    switch (type) {
      case "one-pager":
        return onePagerTemplate(title);
      case "dev-spec":
        return devSpecTemplate(
          title,
          inputs["ONE_PAGER.md"] || "*ONE_PAGER.md not found \u2014 generate it first.*"
        );
      case "prompt-plan":
        return promptPlanTemplate(
          title,
          inputs["ONE_PAGER.md"] || "*ONE_PAGER.md not found*",
          inputs["DEV_SPEC.md"] || "*DEV_SPEC.md not found \u2014 generate it first.*"
        );
      case "agents":
        return agentsTemplate(title, inputs);
      default:
        return `# ${title}

Unknown spec type: ${type}
`;
    }
  }
  /** Check off a specific checkbox item in a stage */
  checkItem(content, stageName, itemIndex) {
    const lines = content.split("\n");
    let inStage = false;
    let itemCount = 0;
    for (let i = 0; i < lines.length; i++) {
      if (lines[i].startsWith("## ") && lines[i].includes(stageName)) {
        inStage = true;
        itemCount = 0;
        continue;
      }
      if (inStage && lines[i].startsWith("## ")) {
        break;
      }
      if (inStage && lines[i].match(/^- \[ \]/)) {
        itemCount++;
        if (itemIndex === void 0 || itemCount === itemIndex) {
          lines[i] = lines[i].replace("- [ ]", "- [x]");
          if (itemIndex !== void 0) break;
        }
      }
    }
    return lines.join("\n");
  }
}
export {
  SpecGeneratorSkill
};
//# sourceMappingURL=spec-generator-skill.js.map
