import { PiExecutor } from "../pi/executor.js";
import { logger } from "../logger.js";
import { FileLock } from "./lock.js";
import type { Config } from "../config.js";

// Categories of autonomous improvements
const IMPROVEMENT_PROMPTS = [
  {
    name: "code-quality",
    prompt: `Analyze the project codebase for code quality issues. Look for:
- Unused imports or variables
- Inconsistent naming conventions
- Missing error handling
- Functions that are too long or complex
- Duplicated code that could be refactored
Fix the top 2-3 most impactful issues you find. Make small, focused changes.`,
  },
  {
    name: "documentation",
    prompt: `Review the project documentation:
- Check if README.md is up to date
- Look for functions/modules missing JSDoc comments
- Check if API endpoints are documented
- Look for outdated or incorrect docs
Fix the most impactful documentation gap you find.`,
  },
  {
    name: "security",
    prompt: `Perform a security review of the codebase:
- Check for hardcoded secrets or credentials
- Look for SQL injection vulnerabilities
- Check for missing input validation
- Review authentication/authorization logic
- Check for insecure dependencies
Report your findings and fix any non-breaking security issues.`,
  },
  {
    name: "type-safety",
    prompt: `Review TypeScript type safety:
- Look for 'any' types that should be properly typed
- Check for missing null checks
- Look for type assertions that could be avoided
- Check for missing return type annotations
Fix the top 2-3 type safety issues.`,
  },
  {
    name: "error-handling",
    prompt: `Review error handling across the project:
- Look for unhandled promise rejections
- Check for missing try/catch blocks
- Look for swallowed errors (empty catch blocks)
- Check if errors are properly logged
- Look for missing error boundaries in React components
Fix the most critical error handling gaps.`,
  },
  {
    name: "performance",
    prompt: `Look for performance issues:
- N+1 query patterns in database calls
- Missing database indexes (check Prisma schema)
- Unnecessary re-renders in React components
- Large bundle imports that could be lazy-loaded
- Missing caching opportunities
Fix 1-2 performance issues if found.`,
  },
  {
    name: "testing",
    prompt: `Review the test coverage:
- Identify critical untested code paths
- Check for test files with failing or skipped tests
- Look for integration test gaps
Write 1-2 new tests for the most critical untested functionality.`,
  },
  {
    name: "dependency-health",
    prompt: `Check project dependencies:
- Look for outdated packages with known vulnerabilities
- Check for unused dependencies
- Look for duplicate dependencies
- Check if lockfile is in sync
Report findings and fix any safe-to-fix issues.`,
  },
];

export class ImprovementLoop {
  private pi: PiExecutor;
  private config: Config;
  private lock: FileLock;
  private running = false;
  private timer: ReturnType<typeof setInterval> | null = null;
  private initialTimeout: ReturnType<typeof setTimeout> | null = null;
  private currentIndex = 0;

  constructor(config: Config) {
    this.config = config;
    this.pi = new PiExecutor(config);
    this.lock = new FileLock("improvement-loop");
  }

  async start() {
    this.running = true;
    logger.info("improvement-loop", "Starting autonomous improvement loop", {
      interval: `${this.config.improvementIntervalSec}s`,
      categories: IMPROVEMENT_PROMPTS.length,
    });

    // Wait a bit before first improvement (let task-loop take priority)
    this.initialTimeout = setTimeout(() => {
      if (this.running) this.runImprovement();
    }, 30_000);

    this.timer = setInterval(
      () => this.runImprovement(),
      this.config.improvementIntervalSec * 1000
    );
  }

  stop() {
    this.running = false;
    if (this.initialTimeout) {
      clearTimeout(this.initialTimeout);
      this.initialTimeout = null;
    }
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
    this.pi.abort();
    this.lock.release();
  }

  private async runImprovement() {
    if (!this.running) return;
    if (!this.lock.acquire()) {
      logger.debug("improvement-loop", "Skipping — another improvement in progress");
      return;
    }

    const improvement = IMPROVEMENT_PROMPTS[this.currentIndex % IMPROVEMENT_PROMPTS.length];
    this.currentIndex++;

    try {
      logger.info("improvement-loop", `Running improvement: ${improvement.name}`);

      const result = await this.pi.execute(improvement.prompt);

      if (result.success) {
        logger.info("improvement-loop", `Improvement completed: ${improvement.name}`, {
          toolCalls: result.toolCalls,
          durationMs: result.durationMs,
        });
      } else {
        logger.warn("improvement-loop", `Improvement failed: ${improvement.name}`, {
          error: result.error,
        });
      }
    } catch (error: any) {
      logger.error("improvement-loop", `Improvement error: ${improvement.name}`, {
        error: error.message,
      });
    } finally {
      this.lock.release();
    }
  }
}
