/**
 * Config Detector - Reads configuration files to extract technologies, versions, and dependencies
 */

import { readFileSync, existsSync } from 'fs';
import { join } from 'path';
import { glob } from 'glob';

/**
 * Detect project configuration
 * @param {string} projectPath - Project root path
 * @returns {Promise<Object>} Configuration detection results
 */
export async function detectConfig(projectPath) {
  const result = {
    language: 'unknown',
    version: null,
    packageManager: 'unknown',
    dependencies: [],
    technologies: [],
    auth: null,
    database: null,
    hosting: null
  };

  // Detect .NET projects
  const dotnetConfig = await detectDotNet(projectPath);
  if (dotnetConfig) {
    Object.assign(result, dotnetConfig);
    return result;
  }

  // Detect Node.js projects
  const nodeConfig = await detectNode(projectPath);
  if (nodeConfig) {
    Object.assign(result, nodeConfig);
    return result;
  }

  return result;
}

/**
 * Detect .NET configuration
 */
async function detectDotNet(projectPath) {
  const programCs = join(projectPath, 'Program.cs');
  const csprojFiles = await glob('**/*.csproj', { cwd: projectPath });

  if (!existsSync(programCs) && csprojFiles.length === 0) {
    return null;
  }

  const config = {
    language: 'csharp',
    version: null,
    packageManager: 'dotnet',
    dependencies: [],
    technologies: [],
    auth: null,
    database: null,
    hosting: null
  };

  // Read Program.cs
  if (existsSync(programCs)) {
    const content = readFileSync(programCs, 'utf8');

    // Detect .NET version
    if (content.includes('WebApplication.CreateBuilder') || content.includes('.NET')) {
      config.version = detectDotNetVersion(content);
    }

    // Detect technologies from Program.cs
    config.technologies = detectTechnologiesFromProgramCs(content);
    config.auth = detectAuthMethod(content);
    config.database = detectDatabase(content);
    config.hosting = detectHosting(content);
  }

  // Read .csproj files
  for (const csprojFile of csprojFiles.slice(0, 3)) { // Read first 3 csproj files
    const csprojPath = join(projectPath, csprojFile);
    const content = readFileSync(csprojPath, 'utf8');

    config.dependencies.push(...extractNuGetPackages(content));
  }

  // Remove duplicates
  config.dependencies = [...new Set(config.dependencies)];
  config.technologies = [...new Set(config.technologies)];

  return config;
}

/**
 * Detect Node.js configuration
 */
async function detectNode(projectPath) {
  const packageJsonPath = join(projectPath, 'package.json');

  if (!existsSync(packageJsonPath)) {
    return null;
  }

  const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));

  const config = {
    language: 'javascript',
    version: packageJson.engines?.node || null,
    packageManager: existsSync(join(projectPath, 'yarn.lock')) ? 'yarn' :
                    existsSync(join(projectPath, 'pnpm-lock.yaml')) ? 'pnpm' : 'npm',
    dependencies: [],
    technologies: [],
    auth: null,
    database: null,
    hosting: null
  };

  // Extract dependencies
  const allDeps = {
    ...packageJson.dependencies,
    ...packageJson.devDependencies
  };

  config.dependencies = Object.keys(allDeps);

  // Detect technologies
  if (allDeps['next']) config.technologies.push('Next.js');
  if (allDeps['react']) config.technologies.push('React');
  if (allDeps['@clerk/nextjs']) config.auth = 'Clerk';
  if (allDeps['prisma']) config.database = 'Prisma';

  return config;
}

/**
 * Detect .NET version from Program.cs
 */
function detectDotNetVersion(content) {
  if (content.includes('.NET 10') || content.includes('net10.0')) return '.NET 10';
  if (content.includes('.NET 9') || content.includes('net9.0')) return '.NET 9';
  if (content.includes('.NET 8') || content.includes('net8.0')) return '.NET 8';
  return 'unknown';
}

/**
 * Detect technologies from Program.cs
 */
function detectTechnologiesFromProgramCs(content) {
  const techs = [];

  if (content.includes('AddBlazor') || content.includes('MapBlazorHub')) {
    techs.push('Blazor Server');
  }

  if (content.includes('AddHangfire')) {
    techs.push('Hangfire');
  }

  if (content.includes('IChatClient') || content.includes('Microsoft.Agents')) {
    techs.push('Microsoft Agent Framework');
  }

  if (content.includes('AddDbContext') || content.includes('UseSqlServer')) {
    techs.push('Entity Framework Core');
  }

  if (content.includes('AddFluentUIComponents') || content.includes('FluentUI')) {
    techs.push('Fluent UI Blazor');
  }

  if (content.includes('AddMudServices') || content.includes('MudBlazor')) {
    techs.push('MudBlazor');
  }

  return techs;
}

/**
 * Detect authentication method
 */
function detectAuthMethod(content) {
  if (content.includes('AddClerk') || content.includes('Clerk')) return 'Clerk';
  if (content.includes('AddMicrosoftIdentity') || content.includes('Entra')) return 'Microsoft Entra';
  if (content.includes('AddAuthentication')) return 'ASP.NET Identity';
  return null;
}

/**
 * Detect database
 */
function detectDatabase(content) {
  if (content.includes('UseSqlServer')) return 'SQL Server';
  if (content.includes('UsePostgres')) return 'PostgreSQL';
  if (content.includes('UseSqlite')) return 'SQLite';
  if (content.includes('UseCosmos')) return 'Cosmos DB';
  return null;
}

/**
 * Detect hosting platform
 */
function detectHosting(content) {
  if (content.includes('Azure') || content.includes('AddAzure')) return 'Azure';
  if (content.includes('AWS')) return 'AWS';
  return null;
}

/**
 * Extract NuGet packages from .csproj
 */
function extractNuGetPackages(csprojContent) {
  const packages = [];
  const regex = /<PackageReference\s+Include="([^"]+)"/g;
  let match;

  while ((match = regex.exec(csprojContent)) !== null) {
    packages.push(match[1]);
  }

  return packages;
}
