/**
 * VL Auto-Fix Engine – automatically fixes common VL syntax issues
 *
 * After VLValidate identifies issues, this engine can fix many of them automatically.
 * This is only possible because VL has strict, deterministic rules.
 * Generic languages can't offer this – you can't auto-fix Python style issues
 * without understanding semantics. VL's fixed structure makes this trivial.
 *
 * Auto-fixable issues:
 *   1. Missing version header → insert // VL_VERSION:3.7
 *   2. Space indentation → convert to dash indentation
 *   3. Section ordering → reorder sections
 *   4. Escape characters → remove or replace
 *   5. PascalCase variables → convert to camelCase
 *   6. Missing root component → add stub
 */
import fs from 'fs/promises';
import path from 'path';
import { VL_VERSION_HEADER } from '../data/versions.js';

export class VLAutoFix {
  constructor(projectContext) {
    this.ctx = projectContext;
  }

  /**
   * Auto-fix a single file. Returns { fixed, changes, content }
   * Does NOT write to disk – caller decides whether to apply
   */
  async fix(filePath) {
    const fullPath = path.resolve(this.ctx.workDir, filePath);
    const ext = path.extname(filePath);
    let content;
    try {
      content = await fs.readFile(fullPath, 'utf-8');
    } catch (err) {
      return { fixed: false, changes: [], error: err.message };
    }

    const changes = [];
    let lines = content.split('\n');

    // Fix 1: Missing version header
    const hasVersion = lines.some(l => l.match(/\/\/\s*VL_VERSION:\S+/));
    if (!hasVersion) {
      lines.unshift(VL_VERSION_HEADER);
      changes.push({ type: 'add_version', line: 1, description: `Added ${VL_VERSION_HEADER} header` });
    }

    // Fix 2: Space indentation → dash indentation
    for (let i = 0; i < lines.length; i++) {
      const spaceMatch = lines[i].match(/^( {2,})(-|<|\$)/);
      if (spaceMatch) {
        const spaces = spaceMatch[1].length;
        const dashes = '-'.repeat(Math.ceil(spaces / 2));
        lines[i] = dashes + lines[i].trimStart();
        changes.push({ type: 'fix_indent', line: i + 1, description: `Converted ${spaces} spaces to dash indentation` });
      }
    }

    // Fix 3: Section ordering
    const sectionOrder = SECTION_ORDER[ext];
    if (sectionOrder) {
      const reordered = this.reorderSections(lines, sectionOrder);
      if (reordered.changed) {
        lines = reordered.lines;
        changes.push({ type: 'reorder_sections', description: `Reordered sections to match VL ${ext} spec` });
      }
    }

    // Fix 4: Escape characters → remove
    for (let i = 0; i < lines.length; i++) {
      if (lines[i].includes('\\n')) {
        lines[i] = lines[i].replace(/\\n/g, '\n');
        changes.push({ type: 'remove_escape', line: i + 1, description: 'Removed \\n escape character' });
      }
      if (lines[i].includes('\\t')) {
        lines[i] = lines[i].replace(/\\t/g, '  ');
        changes.push({ type: 'remove_escape', line: i + 1, description: 'Removed \\t escape character' });
      }
    }

    // Fix 5: $PascalCase variables → $camelCase
    for (let i = 0; i < lines.length; i++) {
      const varMatches = [...lines[i].matchAll(/\$([A-Z][a-zA-Z]*)\(/g)];
      for (const m of varMatches) {
        const fixed = m[1][0].toLowerCase() + m[1].slice(1);
        lines[i] = lines[i].replace(`$${m[1]}(`, `$${fixed}(`);
        changes.push({ type: 'fix_naming', line: i + 1, description: `Renamed $${m[1]} → $${fixed} (camelCase)` });
      }
    }

    const newContent = lines.join('\n');
    return {
      fixed: changes.length > 0,
      changes,
      content: newContent,
      originalContent: content,
    };
  }

  /**
   * Auto-fix and write to disk
   */
  async fixAndSave(filePath) {
    const result = await this.fix(filePath);
    if (!result.fixed) return result;

    const fullPath = path.resolve(this.ctx.workDir, filePath);
    await fs.writeFile(fullPath, result.content, 'utf-8');
    return result;
  }

  /**
   * Auto-fix all VL files in the project
   */
  async fixAll() {
    const results = [];
    let totalChanges = 0;

    for (const file of this.ctx.getAllFiles()) {
      const result = await this.fix(file.path);
      if (result.fixed) {
        results.push({ file: file.path, changes: result.changes });
        totalChanges += result.changes.length;
      }
    }

    return { filesFixed: results.length, totalChanges, results };
  }

  /** Reorder sections within a file to match expected order */
  reorderSections(lines, expectedOrder) {
    // Parse file into sections
    const sections = [];
    let currentSection = { name: '__preamble__', lines: [] };
    sections.push(currentSection);

    for (const line of lines) {
      const match = line.match(/^#\s+(.+)$/);
      if (match) {
        currentSection = { name: match[1].trim(), headerLine: line, lines: [] };
        sections.push(currentSection);
      } else {
        currentSection.lines.push(line);
      }
    }

    // Check if already in order
    const sectionNames = sections.filter(s => s.name !== '__preamble__').map(s => s.name);
    const knownSections = sectionNames.filter(n => expectedOrder.includes(n));
    let isInOrder = true;
    let lastIdx = -1;
    for (const name of knownSections) {
      const idx = expectedOrder.indexOf(name);
      if (idx < lastIdx) { isInOrder = false; break; }
      lastIdx = idx;
    }

    if (isInOrder) return { changed: false, lines };

    // Reorder: preamble first, then sections in expected order, then unknown sections at end
    const preamble = sections.find(s => s.name === '__preamble__');
    const knownMap = new Map(sections.filter(s => expectedOrder.includes(s.name)).map(s => [s.name, s]));
    const unknownSections = sections.filter(s => s.name !== '__preamble__' && !expectedOrder.includes(s.name));

    const reordered = [];
    reordered.push(...preamble.lines);

    for (const name of expectedOrder) {
      const sec = knownMap.get(name);
      if (sec) {
        reordered.push(sec.headerLine);
        reordered.push(...sec.lines);
      }
    }

    for (const sec of unknownSections) {
      reordered.push(sec.headerLine);
      reordered.push(...sec.lines);
    }

    return { changed: true, lines: reordered };
  }
}

const SECTION_ORDER = {
  '.vx': [
    'SysConfig', 'Frontend Global Vars', 'Frontend Derived Vars', 'Frontend Tree',
    'Frontend Event Handlers', 'Frontend Internal Methods', 'Frontend Pipeline Funcs',
  ],
  '.sc': [
    'Frontend Public Props', 'Frontend Public Events', 'Frontend Public Methods',
    'Frontend Global Vars', 'Frontend Derived Vars', 'Frontend Tree',
    'Frontend Event Handlers', 'Frontend Internal Methods', 'Frontend Pipeline Funcs',
  ],
  '.cp': [
    'Frontend Public Props', 'Frontend Public Events',
    'Frontend Derived Vars', 'Frontend Tree',
    'Frontend Event Handlers', 'Frontend Internal Methods', 'Frontend Pipeline Funcs',
  ],
  '.vs': [
    'Backend Environment Vars', 'Backend Tree', 'Services',
    'Backend Event Handlers', 'Transactions',
    'Backend Internal Methods', 'Backend Pipeline Funcs',
  ],
};
