import fs from 'fs-extra';
import path from 'path';

export interface DetectedFramework {
  name: string;
  type: 'backend' | 'frontend' | 'fullstack' | 'generic';
  language: string;
}

export class FrameworkDetector {
  private static FRAMEWORK_MAP: Record<string, { name: string, type: 'backend' | 'frontend' | 'fullstack' | 'generic', language: string }> = {
    // Node.js Backend
    'express': { name: 'Express', type: 'backend', language: 'javascript' },
    'nestjs': { name: 'NestJS', type: 'backend', language: 'typescript' },
    '@nestjs/core': { name: 'NestJS', type: 'backend', language: 'typescript' },
    'fastify': { name: 'Fastify', type: 'backend', language: 'javascript' },
    'koa': { name: 'Koa', type: 'backend', language: 'javascript' },
    'hapi': { name: 'Hapi', type: 'backend', language: 'javascript' },
    'adonisjs': { name: 'AdonisJS', type: 'backend', language: 'javascript' },

    // Node.js Frontend/Fullstack
    'react': { name: 'React', type: 'frontend', language: 'javascript' },
    'vue': { name: 'Vue', type: 'frontend', language: 'javascript' },
    'next': { name: 'Next.js', type: 'fullstack', language: 'javascript' },
    'nuxt': { name: 'Nuxt.js', type: 'fullstack', language: 'javascript' },
    '@sveltejs/kit': { name: 'SvelteKit', type: 'fullstack', language: 'javascript' },
    'svelte': { name: 'Svelte', type: 'frontend', language: 'javascript' },
    '@angular/core': { name: 'Angular', type: 'frontend', language: 'javascript' },

    // Python
    'django': { name: 'Django', type: 'backend', language: 'python' },
    'flask': { name: 'Flask', type: 'backend', language: 'python' },
    'fastapi': { name: 'FastAPI', type: 'backend', language: 'python' },

    // Go
    'github.com/gin-gonic/gin': { name: 'Gin', type: 'backend', language: 'go' },
    'github.com/labstack/echo': { name: 'Echo', type: 'backend', language: 'go' },
    'github.com/gofiber/fiber': { name: 'Fiber', type: 'backend', language: 'go' },

    // PHP
    'laravel/framework': { name: 'Laravel', type: 'backend', language: 'php' },
    'symfony/framework-bundle': { name: 'Symfony', type: 'backend', language: 'php' },

    // Java
    'spring-boot': { name: 'Spring Boot', type: 'backend', language: 'java' },
    'hibernate': { name: 'Hibernate', type: 'backend', language: 'java' },

    // Ruby
    'rails': { name: 'Rails', type: 'fullstack', language: 'ruby' },
    'sinatra': { name: 'Sinatra', type: 'backend', language: 'ruby' },
  };

  static async detect(projectPath: string): Promise<DetectedFramework[]> {
    const frameworks: DetectedFramework[] = [];
    const absolutePath = path.resolve(projectPath);

    // 1. Check Node.js (package.json)
    const pkgPath = path.join(absolutePath, 'package.json');
    if (await fs.pathExists(pkgPath)) {
      try {
        const pkg = await fs.readJson(pkgPath);
        const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
        for (const [dep, info] of Object.entries(this.FRAMEWORK_MAP)) {
          if (deps[dep] && (info.language === 'javascript' || info.language === 'typescript')) {
            frameworks.push(info);
          }
        }
      } catch (e) {}
    }

    // 2. Check Python (requirements.txt, pyproject.toml)
    const reqPath = path.join(absolutePath, 'requirements.txt');
    if (await fs.pathExists(reqPath)) {
      const content = await fs.readFile(reqPath, 'utf-8');
      for (const [dep, info] of Object.entries(this.FRAMEWORK_MAP)) {
        if (info.language === 'python' && content.toLowerCase().includes(dep)) {
          frameworks.push(info);
        }
      }
    }

    // 3. Check Go (go.mod)
    const goModPath = path.join(absolutePath, 'go.mod');
    if (await fs.pathExists(goModPath)) {
      const content = await fs.readFile(goModPath, 'utf-8');
      for (const [dep, info] of Object.entries(this.FRAMEWORK_MAP)) {
        if (info.language === 'go' && content.includes(dep)) {
          frameworks.push(info);
        }
      }
    }

    // 4. Check PHP (composer.json)
    const composerPath = path.join(absolutePath, 'composer.json');
    if (await fs.pathExists(composerPath)) {
      try {
        const composer = await fs.readJson(composerPath);
        const deps = { ...(composer.require || {}), ...(composer['require-dev'] || {}) };
        for (const [dep, info] of Object.entries(this.FRAMEWORK_MAP)) {
          if (deps[dep] && info.language === 'php') {
            frameworks.push(info);
          }
        }
      } catch (e) {}
    }

    // 5. Check Java (pom.xml, build.gradle)
    const pomPath = path.join(absolutePath, 'pom.xml');
    if (await fs.pathExists(pomPath)) {
      const content = await fs.readFile(pomPath, 'utf-8');
      for (const [dep, info] of Object.entries(this.FRAMEWORK_MAP)) {
        if (info.language === 'java' && content.includes(dep)) {
          frameworks.push(info);
        }
      }
    }
    const gradlePath = path.join(absolutePath, 'build.gradle');
    if (await fs.pathExists(gradlePath)) {
      const content = await fs.readFile(gradlePath, 'utf-8');
      for (const [dep, info] of Object.entries(this.FRAMEWORK_MAP)) {
        if (info.language === 'java' && content.includes(dep)) {
          frameworks.push(info);
        }
      }
    }

    // 6. Check Ruby (Gemfile)
    const gemfilePath = path.join(absolutePath, 'Gemfile');
    if (await fs.pathExists(gemfilePath)) {
      const content = await fs.readFile(gemfilePath, 'utf-8');
      for (const [dep, info] of Object.entries(this.FRAMEWORK_MAP)) {
        if (info.language === 'ruby' && content.toLowerCase().includes(`gem '${dep}'`) || content.toLowerCase().includes(`gem "${dep}"`)) {
          frameworks.push(info);
        }
      }
    }

    // Deduplicate and return
    return Array.from(new Set(frameworks.map(f => JSON.stringify(f)))).map(s => JSON.parse(s));
  }
}
