import { NextRequest, NextResponse } from 'next/server';
import os from 'os';
import fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';
import { verifyAdminAuth } from '@/lib/auth';

// Get system stats
function getSystemStats() {
  const cpus = os.cpus();
  const totalMem = os.totalmem();
  const freeMem = os.freemem();
  const usedMem = totalMem - freeMem;
  const uptime = os.uptime();

  // CPU usage (approximate from load average)
  const loadAvg = os.loadavg();
  const cpuCount = cpus.length;
  const cpuUsage = Math.min((loadAvg[0] / cpuCount) * 100, 100);

  // Disk usage
  let diskTotal = 0;
  let diskUsed = 0;
  let diskAvailable = 0;
  try {
    const dfOutput = execSync('df -k / 2>/dev/null || echo "0 0 0"', { encoding: 'utf-8' });
    const lines = dfOutput.trim().split('\n');
    if (lines.length >= 2) {
      const parts = lines[1].split(/\s+/);
      if (parts.length >= 4) {
        diskTotal = parseInt(parts[1]) * 1024;
        diskUsed = parseInt(parts[2]) * 1024;
        diskAvailable = parseInt(parts[3]) * 1024;
      }
    }
  } catch {
    // Fallback: estimate
    diskTotal = 10 * 1024 * 1024 * 1024; // 10GB
    diskUsed = 3 * 1024 * 1024 * 1024; // 3GB used
    diskAvailable = 7 * 1024 * 1024 * 1024;
  }

  // Format uptime
  const days = Math.floor(uptime / 86400);
  const hours = Math.floor((uptime % 86400) / 3600);
  const minutes = Math.floor((uptime % 3600) / 60);
  const seconds = Math.floor(uptime % 60);
  const uptimeStr = `${days}.${String(hours).padStart(2, '0')}.${String(minutes).padStart(2, '0')}.${String(seconds).padStart(2, '0')}`;

  // Node.js version
  const nodeVersion = process.version;

  // Next.js version
  let nextVersion = '16.x';
  try {
    const pkgPath = path.join(process.cwd(), 'node_modules', 'next', 'package.json');
    const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
    nextVersion = pkg.version || '16.x';
  } catch { /* ignore */ }

  // Project version
  let projectVersion = '1.0.0';
  try {
    const pkgPath = path.join(process.cwd(), 'package.json');
    const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
    projectVersion = pkg.version || '1.0.0';
  } catch { /* ignore */ }

  // Memory usage of the process
  const memUsage = process.memoryUsage();
  const rssMB = Math.round(memUsage.rss / 1024 / 1024);
  const heapUsedMB = Math.round(memUsage.heapUsed / 1024 / 1024);
  const heapTotalMB = Math.round(memUsage.heapTotal / 1024 / 1024);

  // SQLite database size
  let dbSize = 0;
  let dbPathStr = '';
  try {
    const possiblePaths = [
      path.join(process.cwd(), 'db', 'dev.db'),
      path.join(process.cwd(), 'prisma', 'dev.db'),
      path.join(process.cwd(), 'dev.db'),
    ];
    for (const p of possiblePaths) {
      if (fs.existsSync(p)) {
        const stat = fs.statSync(p);
        dbSize = stat.size;
        dbPathStr = p;
        break;
      }
    }
  } catch { /* ignore */ }

  // Uploads directory size
  let uploadsSize = 0;
  try {
    const uploadsDir = path.join(process.cwd(), 'public', 'uploads');
    if (fs.existsSync(uploadsDir)) {
      const result = execSync(`du -sb ${uploadsDir} 2>/dev/null || echo 0`, { encoding: 'utf-8' });
      uploadsSize = parseInt(result.split('\t')[0]) || 0;
    }
  } catch { /* ignore */ }

  // Check for warnings
  const warnings: { level: string; title: string; description: string }[] = [];
  const diskPercent = diskTotal > 0 ? (diskUsed / diskTotal) * 100 : 0;
  if (diskPercent > 90) {
    warnings.push({ level: 'critical', title: 'Low Disk Space', description: `Disk is ${diskPercent.toFixed(1)}% full. Free up space immediately.` });
  } else if (diskPercent > 80) {
    warnings.push({ level: 'warning', title: 'Low Disk Space', description: `Disk is ${diskPercent.toFixed(1)}% full. Consider freeing up space.` });
  }

  const memPercent = (usedMem / totalMem) * 100;
  if (memPercent > 90) {
    warnings.push({ level: 'critical', title: 'High Memory Usage', description: `Memory is ${memPercent.toFixed(1)}% used. The server may become unresponsive.` });
  }

  // Check if storage link exists
  let storageLinked = false;
  try {
    const storageLink = path.join(process.cwd(), 'public', 'storage');
    storageLinked = fs.existsSync(storageLink);
  } catch { /* ignore */ }

  // Count API routes
  let apiRouteCount = 0;
  try {
    const apiDir = path.join(process.cwd(), 'src', 'app', 'api');
    const countRoutes = (dir: string): number => {
      let count = 0;
      const entries = fs.readdirSync(dir, { withFileTypes: true });
      for (const entry of entries) {
        if (entry.isDirectory()) {
          count += countRoutes(path.join(dir, entry.name));
        } else if (entry.name === 'route.ts' || entry.name === 'route.js') {
          count++;
        }
      }
      return count;
    };
    apiRouteCount = countRoutes(apiDir);
  } catch { /* ignore */ }

  // Check for update.zip file
  let updateAvailable = false;
  let updateInfo: { version?: string; date?: string; size?: number } | null = null;
  try {
    const updatePath = path.join(process.cwd(), 'update.zip');
    if (fs.existsSync(updatePath)) {
      updateAvailable = true;
      const stat = fs.statSync(updatePath);
      updateInfo = { size: stat.size, date: stat.mtime.toISOString() };
    }
  } catch { /* ignore */ }

  return {
    cpu: {
      usage: cpuUsage.toFixed(2),
      cores: cpuCount,
      model: cpus[0]?.model || 'Unknown',
      loadAvg: loadAvg.map(l => l.toFixed(2)),
    },
    memory: {
      total: totalMem,
      used: usedMem,
      free: freeMem,
      percent: ((usedMem / totalMem) * 100).toFixed(2),
      processRSS: rssMB,
      processHeapUsed: heapUsedMB,
      processHeapTotal: heapTotalMB,
    },
    disk: {
      total: diskTotal,
      used: diskUsed,
      available: diskAvailable,
      percent: diskTotal > 0 ? ((diskUsed / diskTotal) * 100).toFixed(2) : '0',
    },
    uptime: uptimeStr,
    uptimeSeconds: uptime,
    versions: {
      node: nodeVersion,
      next: nextVersion,
      project: projectVersion,
    },
    database: {
      size: dbSize,
      path: dbPathStr,
    },
    uploads: {
      size: uploadsSize,
    },
    storage: {
      linked: storageLinked,
    },
    apiRoutes: apiRouteCount,
    warnings,
    update: {
      available: updateAvailable,
      info: updateInfo,
    },
    timestamp: new Date().toISOString(),
  };
}

// GET - Get server status
export async function GET(req: NextRequest) {
  const authResult = await verifyAdminAuth(req);
  if ('error' in authResult) {
    return authResult.error;
  }

  try {
    const stats = getSystemStats();
    return NextResponse.json({ success: true, stats });
  } catch (error: unknown) {
    const message = error instanceof Error ? error.message : 'Unknown error';
    return NextResponse.json({ success: false, error: message }, { status: 500 });
  }
}

// POST - Run maintenance actions
export async function POST(req: NextRequest) {
  const authResult = await verifyAdminAuth(req);
  if ('error' in authResult) {
    return authResult.error;
  }

  // Only super admin can run maintenance
  if (authResult.session.role !== 'super_admin') {
    return NextResponse.json({ error: 'Only super admin can perform server actions' }, { status: 403 });
  }

  try {
    const body = await req.json();
    const { action } = body;

    switch (action) {
      case 'clear-cache': {
        // Clear Next.js cache
        const cacheDir = path.join(process.cwd(), '.next', 'cache');
        if (fs.existsSync(cacheDir)) {
          fs.rmSync(cacheDir, { recursive: true, force: true });
        }
        return NextResponse.json({ success: true, message: 'Cache cleared successfully' });
      }

      case 'clear-uploads-temp': {
        // Clear temporary upload files
        const tempDir = path.join(process.cwd(), 'public', 'uploads', 'temp');
        let clearedCount = 0;
        if (fs.existsSync(tempDir)) {
          const files = fs.readdirSync(tempDir);
          for (const file of files) {
            const filePath = path.join(tempDir, file);
            const stat = fs.statSync(filePath);
            // Delete files older than 1 hour
            if (Date.now() - stat.mtimeMs > 3600000) {
              fs.unlinkSync(filePath);
              clearedCount++;
            }
          }
        }
        return NextResponse.json({ success: true, message: `Cleared ${clearedCount} temp files` });
      }

      case 'optimize-db': {
        // SQLite optimize (VACUUM)
        try {
          const dbPaths = [
            path.join(process.cwd(), 'db', 'dev.db'),
            path.join(process.cwd(), 'prisma', 'dev.db'),
          ];
          for (const dbP of dbPaths) {
            if (fs.existsSync(dbP)) {
              execSync(`sqlite3 "${dbP}" "VACUUM;" 2>/dev/null || true`);
              break;
            }
          }
        } catch { /* ignore */ }
        return NextResponse.json({ success: true, message: 'Database optimized successfully' });
      }

      case 'run-diagnostics': {
        // Run basic system diagnostics
        const diagnostics: { check: string; status: 'ok' | 'warning' | 'error'; message: string }[] = [];

        // Check disk space
        const stats = getSystemStats();
        const diskPct = parseFloat(stats.disk.percent);
        diagnostics.push({
          check: 'Disk Space',
          status: diskPct > 90 ? 'error' : diskPct > 80 ? 'warning' : 'ok',
          message: `Disk usage: ${diskPct}%`,
        });

        // Check memory
        const memPct = parseFloat(stats.memory.percent);
        diagnostics.push({
          check: 'Memory',
          status: memPct > 90 ? 'error' : memPct > 80 ? 'warning' : 'ok',
          message: `Memory usage: ${memPct}%`,
        });

        // Check database
        diagnostics.push({
          check: 'Database',
          status: stats.database.size > 0 ? 'ok' : 'warning',
          message: stats.database.size > 0
            ? `SQLite database: ${(stats.database.size / 1024 / 1024).toFixed(2)} MB`
            : 'Database file not found',
        });

        // Check Node.js
        diagnostics.push({
          check: 'Node.js',
          status: 'ok',
          message: `Node.js ${stats.versions.node} running`,
        });

        // Check API routes
        diagnostics.push({
          check: 'API Routes',
          status: stats.apiRoutes > 0 ? 'ok' : 'error',
          message: `${stats.apiRoutes} API routes active`,
        });

        return NextResponse.json({ success: true, diagnostics });
      }

      case 'check-updates': {
        // Check for update.zip
        const updatePath = path.join(process.cwd(), 'update.zip');
        const exists = fs.existsSync(updatePath);
        return NextResponse.json({
          success: true,
          updateAvailable: exists,
          message: exists ? 'Update file found. You can deploy it.' : 'No update.zip file found. Upload one to update.',
        });
      }

      case 'deploy-update': {
        // This is handled by the upload API now
        return NextResponse.json({ success: false, message: 'Use the upload endpoint to deploy updates.' });
      }

      default:
        return NextResponse.json({ success: false, error: 'Unknown action' }, { status: 400 });
    }
  } catch (error: unknown) {
    const message = error instanceof Error ? error.message : 'Unknown error';
    return NextResponse.json({ success: false, error: message }, { status: 500 });
  }
}
