/**
 * Evaluation framework — quality gates, code review, TDD, security review.
 * Also includes verification loops and harness audit scoring.
 */
import chalk from 'chalk';
import { execSync } from 'node:child_process';
import { existsSync, statSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import { isGitRepo, gitDiff, gitStatus } from './git-workflow.js';
// ── Code Review Prompt ────────────────────────────────────
export function buildReviewPrompt(cwd, target) {
    if (!isGitRepo(cwd))
        return null;
    const diff = target
        ? execSafe(`git diff ${target}`, cwd)
        : gitDiff(cwd, false) || gitDiff(cwd, true);
    if (!diff)
        return null;
    return `Perform a thorough code review of the following changes.

\`\`\`diff
${diff.slice(0, 15000)}
\`\`\`

Review for:
1. **Correctness** — Logic errors, edge cases, off-by-one
2. **Security** — Injection, XSS, secrets, path traversal, auth issues
3. **Performance** — N+1 queries, unbounded loops, memory leaks
4. **Maintainability** — Naming, complexity, dead code, duplication
5. **Testing** — Are tests adequate? What's missing?

For each issue found, specify:
- File and line number
- Severity: CRITICAL / HIGH / MEDIUM / LOW / NIT
- What's wrong and how to fix it

End with an overall verdict: APPROVE / REQUEST CHANGES / NEEDS DISCUSSION`;
}
// ── TDD Prompt ────────────────────────────────────────────
export function buildTDDPrompt(description) {
    return `I want to implement: ${description}

Follow strict TDD methodology:

**Step 1 — RED**: Write a failing test first.
- Use the project's existing test framework (detect from package.json, pytest.ini, etc.)
- The test should define the expected behavior clearly
- Run the test and show it fails

**Step 2 — GREEN**: Write the minimal code to make the test pass.
- Only write enough code to pass the test
- No extra functionality
- Run the test and show it passes

**Step 3 — REFACTOR**: Clean up if needed.
- Remove duplication
- Improve naming
- Ensure tests still pass

Repeat for each behavior. Show test output after each step.`;
}
// ── Security Review Prompt ────────────────────────────────
export function buildSecurityReviewPrompt(cwd) {
    return `Perform a security review of this project at ${cwd}.

Check for:
1. **Injection vulnerabilities** — SQL, command, XSS, template
2. **Authentication/Authorization** — Missing auth checks, weak sessions
3. **Secrets management** — Hardcoded credentials, API keys in code
4. **Input validation** — Missing validation, type coercion issues
5. **Dependency vulnerabilities** — Check package.json/requirements.txt for known CVEs
6. **File system** — Path traversal, unsafe file operations
7. **Network** — HTTPS enforcement, CORS misconfiguration
8. **Cryptography** — Weak algorithms, improper key management

For each finding:
- Severity: CRITICAL / HIGH / MEDIUM / LOW
- Location: file:line
- Description and remediation

Start by scanning the project structure, then read key files.`;
}
// ── Implementation Plan Prompt ────────────────────────────
export function buildPlanPrompt(task, cwd) {
    return `Task: ${task}

Working directory: ${cwd}

Create a detailed implementation plan:

**Phase Breakdown**:
For each phase, include:
- Phase number and name
- Dependencies (what phases must complete first)
- Files to create or modify (with paths)
- Estimated complexity (1-5, where 5 is most complex)
- Key implementation details

**File Inventory**:
List each file that will be created or modified with:
- Full file path (relative to ${cwd})
- Purpose/reason for change
- Rough line count estimate if applicable

**Edge Cases & Testing**:
- Identify 3-5 edge cases to handle
- Suggest test scenarios for each phase
- Note any integration points with existing code

**Implementation Order**:
Number your phases in dependency order so each can be built on previous ones.

Output as a numbered list with clear formatting.`;
}
// ── E2E Test Generation Prompt ─────────────────────────────
export function buildE2EPrompt(target, cwd) {
    const framework = detectE2EFramework(cwd);
    return `Generate end-to-end tests for: ${target}

Framework: ${framework}
Working directory: ${cwd}

**Testing Strategy**:

1. **Page Object Model Pattern**:
   - Create page objects for main UI components
   - Encapsulate selectors and actions
   - Reuse across test scenarios

2. **Test Scenarios**:
   - **Happy Path**: Normal user workflow for the feature
   - **Error States**: Invalid inputs, API failures, network errors
   - **Edge Cases**: Boundary conditions, race conditions, permission checks
   - **State Transitions**: Moving between different feature states

3. **Test Structure**:
   - Setup: Browser initialization, test data creation
   - Teardown: Cleanup, screenshot on failure
   - Assertions: Verify UI state, API responses, database changes

4. **Coverage Areas**:
   - User interactions (click, type, select, submit)
   - Validation messages and error handling
   - Navigation and routing
   - Asynchronous operations (loading states, waits)

Generate complete, runnable test code with proper error handling and waits.`;
}
// ── Build Error Fix Prompt ─────────────────────────────────
export function buildBuildFixPrompt(cwd, errorOutput) {
    const strategy = errorOutput
        ? `The following build errors were captured:

\`\`\`
${errorOutput.slice(0, 5000)}
\`\`\`

Analyze these errors and fix them one at a time.`
        : `Run the build command in ${cwd} and capture the output.
If there are errors, analyze them and fix them one at a time.
After each fix, re-run the build to verify.`;
    return `${strategy}

**Error Resolution Process**:

For each error found:
1. **Parse** the error message
   - Identify the root cause (missing dependency, syntax error, type error, etc.)
   - Extract file path and line number
   - Note the error category

2. **Fix** the error
   - Make the minimal change to resolve it
   - Don't over-engineer

3. **Verify**
   - Run build/test commands
   - Confirm the error is resolved

4. **Repeat** until build succeeds

**Supported Error Types**:
- TypeScript compilation errors
- Rust build errors
- Go build errors
- Java compilation errors
- Python import/syntax errors

Be methodical and show your work at each step.`;
}
// ── Evaluation Prompt ──────────────────────────────────────
export function buildEvalPrompt(criteria, target) {
    const targetStr = target ? `Target: ${target}\n` : '';
    return `${targetStr}Evaluate against criterion: ${criteria}

**Scoring & Evidence**:

For each sub-criterion or aspect:
1. Score from 1-10 (1=failing, 10=excellent)
2. Provide specific evidence:
   - Point to code examples, metrics, or test results
   - Include exact file paths and line numbers when relevant
   - Cite measurements (e.g., "Lighthouse score: 95/100")
3. Explain your reasoning briefly

**Output Format**:

For each major aspect:
\`\`\`
Aspect: [Name]
Score: [X]/10
Evidence: [specific findings]
Recommendation: [actionable improvement]
\`\`\`

**Final Summary**:
- Overall criterion score (weighted average if multiple aspects)
- Top 3 strengths
- Top 3 areas for improvement
- Specific, actionable next steps

Be specific and evidence-based in your evaluation.`;
}
// ── Documentation Update Prompt ────────────────────────────
export function buildUpdateDocsPrompt(cwd) {
    return `Update project documentation at ${cwd}.

**Documentation Review**:

1. **Find docs**:
   - README.md
   - API documentation (docs/, wiki/, etc.)
   - CHANGELOG.md
   - Code comments and inline docs

2. **Compare with code**:
   - Read the current code
   - Check if docs match implementation
   - Identify outdated sections

3. **Update**:
   - Fix inaccurate sections
   - Add missing features or APIs
   - Update examples with current code
   - Improve unclear explanations

4. **Add**:
   - Document new features not yet documented
   - Add examples for complex features
   - Document configuration options
   - Add troubleshooting sections if missing

Be thorough and ensure all public APIs and features are documented.`;
}
// ── Harness Audit ─────────────────────────────────────────
export function runAudit(cwd) {
    const checks = [];
    // 1. Git repo check
    checks.push(isGitRepo(cwd)
        ? { name: 'Git Repository', result: 'pass', message: 'Project is version controlled', score: 10 }
        : { name: 'Git Repository', result: 'fail', message: 'Not a git repo — version control recommended', score: 0 });
    // 2. Clean working tree
    if (isGitRepo(cwd)) {
        const status = gitStatus(cwd);
        checks.push(!status
            ? { name: 'Clean Working Tree', result: 'pass', message: 'No uncommitted changes', score: 10 }
            : { name: 'Clean Working Tree', result: 'warn', message: `${status.split('\n').length} uncommitted changes`, score: 5 });
    }
    // 3. Package manager lock file
    const hasLockFile = fileExists(cwd, 'package-lock.json') || fileExists(cwd, 'yarn.lock') ||
        fileExists(cwd, 'pnpm-lock.yaml') || fileExists(cwd, 'bun.lock') ||
        fileExists(cwd, 'Cargo.lock') || fileExists(cwd, 'go.sum') ||
        fileExists(cwd, 'poetry.lock') || fileExists(cwd, 'Pipfile.lock');
    checks.push(hasLockFile
        ? { name: 'Lock File', result: 'pass', message: 'Dependency lock file present', score: 10 }
        : { name: 'Lock File', result: 'warn', message: 'No lock file — builds may not be reproducible', score: 3 });
    // 4. Tests exist
    const hasTests = dirExists(cwd, 'test') || dirExists(cwd, 'tests') || dirExists(cwd, '__tests__') ||
        dirExists(cwd, 'spec') || fileExists(cwd, 'jest.config.js') || fileExists(cwd, 'pytest.ini') ||
        fileExists(cwd, 'vitest.config.ts');
    checks.push(hasTests
        ? { name: 'Test Suite', result: 'pass', message: 'Test directory/config found', score: 15 }
        : { name: 'Test Suite', result: 'fail', message: 'No tests found — testing is essential', score: 0 });
    // 5. .gitignore
    checks.push(fileExists(cwd, '.gitignore')
        ? { name: '.gitignore', result: 'pass', message: '.gitignore present', score: 5 }
        : { name: '.gitignore', result: 'warn', message: 'No .gitignore — may commit unwanted files', score: 2 });
    // 6. README
    const hasReadme = fileExists(cwd, 'README.md') || fileExists(cwd, 'README.txt') || fileExists(cwd, 'README');
    checks.push(hasReadme
        ? { name: 'README', result: 'pass', message: 'README found', score: 5 }
        : { name: 'README', result: 'warn', message: 'No README — documentation recommended', score: 2 });
    // 7. CI/CD
    const hasCI = dirExists(cwd, '.github/workflows') || fileExists(cwd, '.gitlab-ci.yml') ||
        fileExists(cwd, 'Jenkinsfile') || fileExists(cwd, '.circleci/config.yml');
    checks.push(hasCI
        ? { name: 'CI/CD', result: 'pass', message: 'CI/CD configuration found', score: 10 }
        : { name: 'CI/CD', result: 'warn', message: 'No CI/CD — automated testing/deployment recommended', score: 3 });
    // 8. No secrets in repo
    const secretsCheck = checkForSecrets(cwd);
    checks.push(secretsCheck);
    // 9. Linter/formatter config
    const hasLinter = fileExists(cwd, '.eslintrc.json') || fileExists(cwd, '.eslintrc.js') ||
        fileExists(cwd, 'biome.json') || fileExists(cwd, '.prettierrc') ||
        fileExists(cwd, 'rustfmt.toml') || fileExists(cwd, '.golangci.yml') ||
        fileExists(cwd, 'setup.cfg') || fileExists(cwd, 'pyproject.toml');
    checks.push(hasLinter
        ? { name: 'Linter/Formatter', result: 'pass', message: 'Code quality tool configured', score: 10 }
        : { name: 'Linter/Formatter', result: 'warn', message: 'No linter/formatter — code consistency at risk', score: 3 });
    // 10. TypeScript strict (if applicable)
    if (fileExists(cwd, 'tsconfig.json')) {
        const tsCheck = checkTSStrict(cwd);
        checks.push(tsCheck);
    }
    // Calculate totals
    const totalScore = checks.reduce((s, c) => s + c.score, 0);
    const maxScore = checks.length * 15; // max 15 per check
    const pct = (totalScore / maxScore) * 100;
    const grade = pct >= 90 ? 'A' : pct >= 75 ? 'B' : pct >= 60 ? 'C' : pct >= 40 ? 'D' : 'F';
    return { checks, totalScore, maxScore, grade };
}
export function printAuditReport(report) {
    const gradeColor = { A: chalk.green, B: chalk.cyan, C: chalk.yellow, D: chalk.red, F: chalk.bgRed.white };
    const gc = gradeColor[report.grade] || chalk.white;
    console.log(chalk.cyan('\n  Harness Audit Report'));
    console.log(gc(`  Grade: ${report.grade} (${report.totalScore}/${report.maxScore})\n`));
    for (const c of report.checks) {
        const icon = c.result === 'pass' ? chalk.green('✓') : c.result === 'warn' ? chalk.yellow('⚠') : chalk.red('✗');
        console.log(`  ${icon} ${c.name.padEnd(20)} ${chalk.dim(c.message)}`);
    }
    console.log();
}
// ── Helpers ───────────────────────────────────────────────
function fileExists(cwd, name) {
    try {
        return existsSync(join(cwd, name));
    }
    catch {
        return false;
    }
}
function dirExists(cwd, name) {
    try {
        return statSync(join(cwd, name)).isDirectory();
    }
    catch {
        return false;
    }
}
function execSafe(cmd, cwd) {
    try {
        return execSync(cmd, { cwd, encoding: 'utf-8', timeout: 10_000, stdio: 'pipe' }).trim();
    }
    catch {
        return '';
    }
}
function checkForSecrets(cwd) {
    const dangerous = ['.env', '.env.local', '.env.production'];
    const found = [];
    for (const f of dangerous) {
        if (fileExists(cwd, f)) {
            // Check if it's gitignored
            const ignored = execSafe(`git check-ignore ${f}`, cwd);
            if (!ignored)
                found.push(f);
        }
    }
    if (found.length > 0) {
        return {
            name: 'Secrets Safety',
            result: 'fail',
            message: `Unignored secret files: ${found.join(', ')}`,
            score: 0,
        };
    }
    return { name: 'Secrets Safety', result: 'pass', message: 'No exposed secret files', score: 10 };
}
function checkTSStrict(cwd) {
    try {
        const content = readFileSync(join(cwd, 'tsconfig.json'), 'utf-8');
        const isStrict = content.includes('"strict": true') || content.includes('"strict":true');
        return isStrict
            ? { name: 'TS Strict Mode', result: 'pass', message: 'TypeScript strict mode enabled', score: 10 }
            : { name: 'TS Strict Mode', result: 'warn', message: 'TypeScript strict mode not enabled', score: 3 };
    }
    catch {
        return { name: 'TS Strict Mode', result: 'warn', message: 'Could not read tsconfig.json', score: 3 };
    }
}
// ── E2E Framework Detection ────────────────────────────────
export function detectE2EFramework(cwd) {
    try {
        const content = readFileSync(join(cwd, 'package.json'), 'utf-8');
        if (content.includes('"playwright"') || content.includes("'playwright'")) {
            return 'playwright';
        }
        if (content.includes('"cypress"') || content.includes("'cypress'")) {
            return 'cypress';
        }
        if (content.includes('"puppeteer"') || content.includes("'puppeteer'")) {
            return 'puppeteer';
        }
        // Default to Playwright
        return 'playwright';
    }
    catch {
        // Default to Playwright if package.json cannot be read
        return 'playwright';
    }
}
//# sourceMappingURL=evaluation.js.map