/**
 * Spec Initializer Service
 *
 * Creates feature specification directories with YAML template files.
 * Templates match exactly what /shep-kit:new-feature produces,
 * enabling dogfooding — the CLI and the skill use the same spec format.
 */
import { mkdir, readdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
/**
 * Pad a number to 3 digits with leading zeros.
 */
function padNumber(n) {
    return String(n).padStart(3, '0');
}
/**
 * Apply template variable substitution matching init-feature.sh behavior.
 * Handles both {{VAR}} and { { VAR } } (Prettier-formatted) patterns.
 */
function applyTemplate(template, vars) {
    const replacements = [
        [/\{\{ ?NNN ?\}\}|\{ \{ NNN \} \}/g, vars.nnn],
        [/\{\{ ?FEATURE_NAME ?\}\}|\{ \{ FEATURE_NAME \} \}/g, vars.slug],
        [/\{\{ ?FEATURE_ID ?\}\}|\{ \{ FEATURE_ID \} \}/g, `${vars.nnn}-${vars.slug}`],
        [/\{\{ ?FEATURE_NUMBER ?\}\}|\{ \{ FEATURE_NUMBER \} \}/g, String(vars.featureNumber)],
        [/\{\{ ?BRANCH_NAME ?\}\}|\{ \{ BRANCH_NAME \} \}/g, `feat/${vars.nnn}-${vars.slug}`],
        [/\{\{ ?DATE ?\}\}|\{ \{ DATE \} \}/g, vars.date],
        [/\{\{ ?TIMESTAMP ?\}\}|\{ \{ TIMESTAMP \} \}/g, vars.timestamp],
        [/\{\{ ?DESCRIPTION ?\}\}|\{ \{ DESCRIPTION \} \}/g, vars.description],
    ];
    let result = template;
    for (const [pattern, replacement] of replacements) {
        result = result.replace(pattern, replacement);
    }
    return result;
}
// ─── YAML Templates ────────────────────────────────────────────────
// These match .claude/skills/shep-kit-new-feature/templates/ exactly.
const SPEC_YAML = `# Feature Specification (YAML)
# This is the source of truth. Markdown is auto-generated from this file.

name: {{FEATURE_NAME}}
number: {{NNN}}
branch: feat/{{NNN}}-{{FEATURE_NAME}}
oneLiner: {{DESCRIPTION}}
userQuery: >
  {{DESCRIPTION}}
summary: >
  {{DESCRIPTION}}
phase: Analysis
sizeEstimate: M

# Relationships
relatedFeatures:
  []

technologies:
  []

relatedLinks:
  []

# Open questions (must be resolved before implementation)
openQuestions:
  []

# Markdown content (the actual spec)
content: |
  ## Problem Statement

  {{DESCRIPTION}}

  ## Success Criteria

  - [ ] TBD

  ## Affected Areas

  | Area | Impact | Reasoning |
  | ---- | ------ | --------- |
  | TBD  | TBD    | TBD       |

  ## Dependencies

  None identified.

  ## Size Estimate

  **M** - To be refined during research

  ---

  _Generated by feature agent — proceed with research_
`;
const RESEARCH_YAML = `# Research Artifact (YAML)
# This is the source of truth. Markdown is auto-generated from this file.

name: {{FEATURE_NAME}}
summary: Technical analysis for {{NNN}}-{{FEATURE_NAME}}

# Relationships
relatedFeatures: []
technologies: []
relatedLinks: []

# Structured technology decisions
decisions: []

# Open questions (should be resolved by end of research)
openQuestions: []

# Markdown content (the full research document)
content: |
  ## Status

  - **Phase:** Research
  - **Updated:** {{DATE}}

  ## Technology Decisions

  TBD

  ---

  _To be updated during research phase_
`;
const PLAN_YAML = `# Implementation Plan (YAML)
# This is the source of truth. Markdown is auto-generated from this file.

name: {{FEATURE_NAME}}
summary: Implementation plan for {{NNN}}-{{FEATURE_NAME}}

# Relationships
relatedFeatures: []
technologies: []
relatedLinks: []

# Structured implementation phases
phases: []

# File change tracking
filesToCreate: []
filesToModify: []

# Open questions (should all be resolved before implementation)
openQuestions: []

# Markdown content (the full plan document)
content: |
  ## Status

  - **Phase:** Planning
  - **Updated:** {{DATE}}

  ## Implementation Strategy

  TBD

  ---

  _To be updated during planning phase_
`;
const TASKS_YAML = `# Task Breakdown (YAML)
# This is the source of truth. Markdown is auto-generated from this file.

name: {{FEATURE_NAME}}
summary: Task breakdown for {{NNN}}-{{FEATURE_NAME}}

# Relationships
relatedFeatures: []
technologies: []
relatedLinks: []

# Structured task list
tasks: []

# Total effort estimate
totalEstimate: TBD

# Open questions
openQuestions: []

# Markdown content (the full tasks document)
content: |
  ## Status

  - **Phase:** Implementation
  - **Updated:** {{DATE}}

  ## Task List

  TBD

  ---

  _Task breakdown for implementation tracking_
`;
const FEATURE_YAML = `feature:
  id: '{{FEATURE_ID}}'
  name: '{{FEATURE_NAME}}'
  number: {{FEATURE_NUMBER}}
  branch: '{{BRANCH_NAME}}'
  lifecycle: 'research'
  createdAt: '{{TIMESTAMP}}'

status:
  phase: 'research'
  progress:
    completed: 0
    total: 0
    percentage: 0
  currentTask: null
  lastUpdated: '{{TIMESTAMP}}'
  lastUpdatedBy: 'feature-agent'

validation:
  lastRun: null
  gatesPassed: []
  autoFixesApplied: []

tasks:
  current: null
  blocked: []
  failed: []

checkpoints:
  - phase: 'feature-created'
    completedAt: '{{TIMESTAMP}}'
    completedBy: 'feature-agent'

errors:
  current: null
  history: []
`;
const TEMPLATES = [
    { filename: 'spec.yaml', content: SPEC_YAML },
    { filename: 'research.yaml', content: RESEARCH_YAML },
    { filename: 'plan.yaml', content: PLAN_YAML },
    { filename: 'tasks.yaml', content: TASKS_YAML },
    { filename: 'feature.yaml', content: FEATURE_YAML },
];
export class SpecInitializerService {
    async initialize(basePath, slug, featureNumber, description, mode) {
        // Scan existing specs/ directory for highest NNN prefix to avoid collisions
        // (specs may have been created outside the DB, e.g., via /shep-kit:new-feature)
        const resolvedNumber = await this.resolveNextNumber(basePath, featureNumber);
        const nnn = padNumber(resolvedNumber);
        const specDirName = `${nnn}-${slug}`;
        const specDir = join(basePath, 'specs', specDirName);
        // Create the spec directory
        await mkdir(specDir, { recursive: true });
        const now = new Date();
        const date = now.toISOString().split('T')[0];
        const timestamp = now.toISOString().replace(/\.\d{3}Z$/, 'Z');
        const vars = { nnn, slug, featureNumber: resolvedNumber, date, timestamp, description };
        // In fast mode, write feature.yaml + spec.yaml (spec.yaml stores the user query
        // which the fast-implement node reads; no research/plan/tasks needed)
        const templates = mode === 'fast'
            ? TEMPLATES.filter(({ filename }) => filename === 'feature.yaml' || filename === 'spec.yaml')
            : TEMPLATES;
        // Write template files
        await Promise.all(templates.map(({ filename, content }) => writeFile(join(specDir, filename), applyTemplate(content, vars), 'utf-8')));
        return { specDir, featureNumber: nnn };
    }
    /**
     * Scan specs/ for existing NNN-* directories and return the next available number.
     * Uses the DB-derived hint as a minimum, but always respects filesystem state.
     */
    async resolveNextNumber(basePath, hint) {
        const specsDir = join(basePath, 'specs');
        let entries;
        try {
            entries = await readdir(specsDir);
        }
        catch {
            // specs/ doesn't exist yet — use hint
            return hint;
        }
        let maxExisting = 0;
        for (const entry of entries) {
            const match = entry.match(/^(\d{3})-/);
            if (match) {
                maxExisting = Math.max(maxExisting, parseInt(match[1], 10));
            }
        }
        return Math.max(maxExisting + 1, hint);
    }
}
