/**
 * GitHub Repository Analyzer
 * Fetches and analyzes repository structure and key files for AI context
 */

import { getAdminDb } from '@/lib/firebase/admin';

interface RepositoryAnalysis {
  repoFullName: string;
  totalFiles: number;
  fileStructure: {
    directories: string[];
    keyFiles: string[];
  };
  readme: string | null;
  packageJson: Record<string, unknown> | null;
  techStack: string[];
  summary: string;
}

/**
 * Analyze a GitHub repository to extract key information for AI context
 */
export async function analyzeGitHubRepository(
  userId: string,
  repoFullName: string,
  branch = 'main'
): Promise<RepositoryAnalysis | null> {
  try {
    const adminDb = getAdminDb();
    
    // Get GitHub access token
    const connectionDoc = await adminDb
      .collection('githubConnections')
      .doc(userId)
      .get();

    if (!connectionDoc.exists) {
      console.log('[GitHub Analyzer] No GitHub connection found');
      return null;
    }

    const connection = connectionDoc.data()!;
    const accessToken = connection.accessToken;
    const [owner, repo] = repoFullName.split('/');

    // Fetch repository tree
    const treeResponse = await fetch(
      `https://api.github.com/repos/${owner}/${repo}/git/trees/${branch}?recursive=1`,
      {
        headers: {
          Authorization: `Bearer ${accessToken}`,
          Accept: 'application/vnd.github.v3+json',
        },
      }
    );

    if (!treeResponse.ok) {
      console.error('[GitHub Analyzer] Failed to fetch tree:', treeResponse.statusText);
      return null;
    }

    const treeData = await treeResponse.json();
    
    // Extract directories and key files
    const directories = new Set<string>();
    const keyFiles: string[] = [];
    let totalFiles = 0;

    treeData.tree?.forEach((item: { path: string; type: string }) => {
      if (item.type === 'blob') {
        totalFiles++;
        
        // Track key files
        const fileName = item.path.toLowerCase();
        if (
          fileName === 'readme.md' ||
          fileName === 'package.json' ||
          fileName === 'requirements.txt' ||
          fileName === 'cargo.toml' ||
          fileName === 'go.mod' ||
          fileName === 'pom.xml' ||
          fileName.startsWith('dockerfile')
        ) {
          keyFiles.push(item.path);
        }
      }
      
      // Track top-level directories
      const parts = item.path.split('/');
      if (parts.length > 1) {
        directories.add(parts[0]);
      }
    });

    // Fetch README content (truncate to first 3000 chars to avoid bloating prompts)
    let readme: string | null = null;
    const readmePath = keyFiles.find(f => f.toLowerCase().endsWith('readme.md'));
    if (readmePath) {
      const fullReadme = await fetchFileContent(accessToken, owner, repo, readmePath, branch);
      if (fullReadme) {
        // Truncate to first 3000 characters (roughly 750 tokens)
        readme = fullReadme.length > 3000 
          ? fullReadme.substring(0, 3000) + '\n\n[... README truncated for brevity ...]'
          : fullReadme;
      }
    }

    // Fetch package.json content
    let packageJson: Record<string, unknown> | null = null;
    const packageJsonPath = keyFiles.find(f => f.toLowerCase().endsWith('package.json'));
    if (packageJsonPath) {
      const content = await fetchFileContent(accessToken, owner, repo, packageJsonPath, branch);
      if (content) {
        try {
          packageJson = JSON.parse(content);
        } catch (e) {
          console.error('[GitHub Analyzer] Failed to parse package.json');
        }
      }
    }

    // Detect tech stack
    const techStack = detectTechStack(keyFiles, Array.from(directories), packageJson);

    // Generate summary
    const summary = generateRepositorySummary({
      repoFullName,
      totalFiles,
      directories: Array.from(directories),
      keyFiles,
      techStack,
      readme,
      packageJson,
    });

    return {
      repoFullName,
      totalFiles,
      fileStructure: {
        directories: Array.from(directories).slice(0, 20), // Limit to top 20
        keyFiles,
      },
      readme: readme ? readme.substring(0, 2000) : null, // First 2000 chars
      packageJson,
      techStack,
      summary,
    };
  } catch (error) {
    console.error('[GitHub Analyzer] Error analyzing repository:', error);
    return null;
  }
}

/**
 * Fetch file content from GitHub
 */
async function fetchFileContent(
  accessToken: string,
  owner: string,
  repo: string,
  path: string,
  branch: string
): Promise<string | null> {
  try {
    const response = await fetch(
      `https://api.github.com/repos/${owner}/${repo}/contents/${encodeURIComponent(path)}?ref=${branch}`,
      {
        headers: {
          Authorization: `Bearer ${accessToken}`,
          Accept: 'application/vnd.github.v3+json',
        },
      }
    );

    if (!response.ok) return null;

    const data = await response.json();
    return Buffer.from(data.content, 'base64').toString('utf-8');
  } catch (error) {
    console.error(`[GitHub Analyzer] Failed to fetch ${path}:`, error);
    return null;
  }
}

/**
 * Detect tech stack from repository structure
 */
function detectTechStack(
  keyFiles: string[],
  directories: string[],
  packageJson: Record<string, unknown> | null
): string[] {
  const stack: string[] = [];

  // From key files
  if (keyFiles.some(f => f.toLowerCase().includes('package.json'))) {
    stack.push('Node.js/JavaScript');
    
    if (packageJson) {
      const deps = { 
        ...(packageJson.dependencies as Record<string, unknown> || {}), 
        ...(packageJson.devDependencies as Record<string, unknown> || {}) 
      };
      
      if (deps.next) stack.push('Next.js');
      if (deps.react) stack.push('React');
      if (deps.vue) stack.push('Vue');
      if (deps.express) stack.push('Express');
      if (deps.typescript) stack.push('TypeScript');
    }
  }
  
  if (keyFiles.some(f => f.toLowerCase().includes('requirements.txt') || f.toLowerCase().includes('pyproject.toml'))) {
    stack.push('Python');
  }
  
  if (keyFiles.some(f => f.toLowerCase().includes('cargo.toml'))) {
    stack.push('Rust');
  }
  
  if (keyFiles.some(f => f.toLowerCase().includes('go.mod'))) {
    stack.push('Go');
  }
  
  if (keyFiles.some(f => f.toLowerCase().includes('pom.xml') || f.toLowerCase().includes('build.gradle'))) {
    stack.push('Java');
  }
  
  if (keyFiles.some(f => f.toLowerCase().startsWith('dockerfile'))) {
    stack.push('Docker');
  }

  // From directories
  if (directories.includes('.github')) stack.push('GitHub Actions');
  if (directories.includes('terraform') || directories.includes('infrastructure')) {
    stack.push('Infrastructure as Code');
  }

  return stack;
}

/**
 * Generate a human-readable summary
 */
function generateRepositorySummary(analysis: {
  repoFullName: string;
  totalFiles: number;
  directories: string[];
  keyFiles: string[];
  techStack: string[];
  readme: string | null;
  packageJson: Record<string, unknown> | null;
}): string {
  const parts: string[] = [];

  parts.push(`## Repository Analysis: ${analysis.repoFullName}`);
  parts.push(`\n**Structure:**`);
  parts.push(`- Total files: ${analysis.totalFiles}`);
  
  if (analysis.directories.length > 0) {
    parts.push(`- Main directories: ${analysis.directories.slice(0, 15).join(', ')}`);
  }
  
  if (analysis.techStack.length > 0) {
    parts.push(`\n**Tech Stack:** ${analysis.techStack.join(', ')}`);
  }
  
  if (analysis.packageJson) {
    const pkg = analysis.packageJson;
    parts.push(`\n**Package Info:**`);
    if (pkg.name) parts.push(`- Name: ${pkg.name}`);
    if (pkg.description) parts.push(`- Description: ${pkg.description}`);
    if (pkg.version) parts.push(`- Version: ${pkg.version}`);
    
    // Show key dependencies
    const deps = pkg.dependencies as Record<string, string> || {};
    const devDeps = pkg.devDependencies as Record<string, string> || {};
    const allDeps = { ...deps, ...devDeps };
    const keyDeps = Object.keys(allDeps).slice(0, 10);
    if (keyDeps.length > 0) {
      parts.push(`- Key dependencies: ${keyDeps.join(', ')}`);
    }
  }
  
  if (analysis.readme) {
    parts.push(`\n**README Content:**`);
    // Get first few paragraphs or up to 1000 chars
    const readmeExcerpt = analysis.readme.substring(0, 1000);
    parts.push(readmeExcerpt);
    if (analysis.readme.length > 1000) {
      parts.push('...(truncated)');
    }
  }

  return parts.join('\n');
}

