/**
 * Structure Detector - Analyzes folder structure to infer stack and architecture
 */

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

/**
 * Detect project structure
 * @param {string} projectPath - Project root path
 * @returns {Promise<Object>} Structure detection results
 */
export async function detectStructure(projectPath) {
  const result = {
    stack: 'unknown',
    architecture: 'unknown',
    uiLibrary: null,
    patterns: [],
    folders: {
      hasPages: false,
      hasComponents: false,
      hasServices: false,
      hasRepositories: false,
      hasAgents: false
    }
  };

  // Detect stack
  result.stack = await detectStack(projectPath);

  // Detect architecture pattern
  result.architecture = await detectArchitecture(projectPath);

  // Detect UI library
  if (result.stack === 'blazor') {
    result.uiLibrary = await detectUILibrary(projectPath);
  }

  // Detect patterns
  result.patterns = await detectPatterns(projectPath);

  // Analyze folders
  result.folders = await analyzeFolders(projectPath);

  return result;
}

/**
 * Detect stack type
 */
async function detectStack(projectPath) {
  // Order matters: more specific patterns first
  const patterns = {
    blazor: [
      '**/*.razor',
      '**/Pages/**/*.razor',
      '**/Components/**/*.razor'
    ],
    nextjs: [
      'next.config.js',
      'next.config.mjs',
      'next.config.ts',
      'pages/**/*.tsx',
      'app/**/*.tsx'
    ],
    shopify: [
      '**/*.liquid',
      'sections/**/*.liquid',
      'templates/**/*.liquid'
    ],
    react: [
      'src/App.jsx',
      'src/App.tsx',
      'vite.config.js',
      'craco.config.js'
    ],
    vue: [
      'vite.config.js', // Vue 3 + Vite
      'vue.config.js',  // Vue 2
      'src/App.vue'
    ],
    dotnet: [
      '**/*.csproj',
      '**/Program.cs'
    ],
    typescript: [
      'tsconfig.json',
      'src/**/*.ts'
    ],
    nodejs: [
      'package.json'  // Fallback: generic Node.js
    ],
    python: [
      'requirements.txt',
      'pyproject.toml',
      'setup.py'
    ],
    go: [
      'go.mod',
      'main.go'
    ]
  };

  for (const [stack, globs] of Object.entries(patterns)) {
    for (const pattern of globs) {
      const files = await glob(pattern, { cwd: projectPath, nodir: true });
      if (files.length > 0) {
        return stack;
      }
    }
  }

  return 'unknown';
}

/**
 * Detect architecture pattern
 */
async function detectArchitecture(projectPath) {
  const checks = [
    {
      pattern: 'clean-architecture',
      indicators: [
        existsSync(join(projectPath, 'src', 'Application')),
        existsSync(join(projectPath, 'src', 'Domain')),
        existsSync(join(projectPath, 'src', 'Infrastructure'))
      ]
    },
    {
      pattern: 'cqrs',
      indicators: [
        await glob('**/Commands/**/*.cs', { cwd: projectPath }).then(f => f.length > 0),
        await glob('**/Queries/**/*.cs', { cwd: projectPath }).then(f => f.length > 0)
      ]
    },
    {
      pattern: 'mvc',
      indicators: [
        existsSync(join(projectPath, 'Controllers')),
        existsSync(join(projectPath, 'Models')),
        existsSync(join(projectPath, 'Views'))
      ]
    }
  ];

  for (const { pattern, indicators } of checks) {
    if (indicators.every(Boolean)) {
      return pattern;
    }
  }

  return 'unknown';
}

/**
 * Detect UI library (Blazor projects)
 */
async function detectUILibrary(projectPath) {
  const csprojFiles = await glob('**/*.csproj', { cwd: projectPath });

  for (const csprojFile of csprojFiles) {
    const content = await import('fs').then(fs =>
      fs.promises.readFile(join(projectPath, csprojFile), 'utf8')
    );

    if (content.includes('FluentUI.Blazor') || content.includes('Microsoft.FluentUI.AspNetCore.Components')) {
      return 'fluent-ui';
    }

    if (content.includes('MudBlazor')) {
      return 'mudblazor';
    }
  }

  return null;
}

/**
 * Detect common patterns
 */
async function detectPatterns(projectPath) {
  const patterns = [];

  // Check for specific patterns
  const checks = [
    {
      name: 'Repository Pattern',
      glob: '**/*Repository.cs'
    },
    {
      name: 'Service Layer',
      glob: '**/*Service.cs'
    },
    {
      name: 'DTOs',
      glob: '**/*Dto.cs'
    },
    {
      name: 'Entity Framework',
      glob: '**/Migrations/**/*.cs'
    },
    {
      name: 'Dependency Injection',
      glob: '**/DependencyInjection.cs'
    },
    {
      name: 'Hangfire Jobs',
      glob: '**/*Job.cs'
    },
    {
      name: 'AI Agents',
      glob: '**/*Agent.cs'
    },
    {
      name: 'Unit Tests',
      glob: '**/*.Tests/**/*.cs'
    }
  ];

  for (const { name, glob: pattern } of checks) {
    const files = await glob(pattern, { cwd: projectPath, nodir: true });
    if (files.length > 0) {
      patterns.push(name);
    }
  }

  return patterns;
}

/**
 * Analyze folder structure
 */
async function analyzeFolders(projectPath) {
  const folders = {
    hasPages: false,
    hasComponents: false,
    hasServices: false,
    hasRepositories: false,
    hasAgents: false
  };

  folders.hasPages = await glob('**/Pages/**/*', { cwd: projectPath }).then(f => f.length > 0);
  folders.hasComponents = await glob('**/Components/**/*', { cwd: projectPath }).then(f => f.length > 0);
  folders.hasServices = await glob('**/Services/**/*', { cwd: projectPath }).then(f => f.length > 0);
  folders.hasRepositories = await glob('**/Repositories/**/*', { cwd: projectPath }).then(f => f.length > 0);
  folders.hasAgents = await glob('**/Agents/**/*', { cwd: projectPath }).then(f => f.length > 0);

  return folders;
}
