import { json } from '@sveltejs/kit';
import {
	getDockerInfo,
	getDockerVersion,
	listContainers,
	listImages,
	listVolumes,
	listNetworks,
	getDockerConnectionInfo
} from '$lib/server/docker';
import { getStackSources } from '$lib/server/db';
import { isPostgres, isSqlite, getDatabaseSchemaVersion, getPostgresConnectionInfo } from '$lib/server/db/drizzle';
import { hasEnvironments } from '$lib/server/db';
import type { RequestHandler } from './$types';
import { existsSync, readFileSync } from 'node:fs';
import * as http from 'node:http';
import os from 'node:os';
import { authorize } from '$lib/server/authorize';

// Detect if running inside a Docker container
function detectContainerRuntime(): { inContainer: boolean; runtime?: string; containerId?: string } {
	// Check for .dockerenv file (Docker)
	if (existsSync('/.dockerenv')) {
		let containerId: string | undefined;
		try {
			// Try to get container ID from hostname (Docker sets it)
			containerId = os.hostname();
			// Validate it looks like a container ID (12+ hex chars)
			if (!/^[a-f0-9]{12,}$/i.test(containerId)) {
				containerId = undefined;
			}
		} catch {}
		return { inContainer: true, runtime: 'docker', containerId };
	}

	// Check cgroup for container indicators
	try {
		if (existsSync('/proc/1/cgroup')) {
			const cgroup = readFileSync('/proc/1/cgroup', 'utf-8');
			if (cgroup.includes('docker') || cgroup.includes('containerd') || cgroup.includes('kubepods')) {
				const runtime = cgroup.includes('kubepods') ? 'kubernetes' :
					cgroup.includes('containerd') ? 'containerd' : 'docker';
				return { inContainer: true, runtime };
			}
		}
	} catch {}

	return { inContainer: false };
}

// Get runtime info
function getRuntimeInfo() {
	const memUsage = process.memoryUsage();
	return {
		name: 'Node.js',
		version: process.version,
		memory: {
			heapUsed: memUsage.heapUsed,
			heapTotal: memUsage.heapTotal,
			rss: memUsage.rss,
			external: memUsage.external
		}
	};
}

// Get info about our own container if running in Docker
async function getOwnContainerInfo(containerId: string | undefined): Promise<any> {
	if (!containerId) return null;

	try {
		const socketPaths = [
			'/var/run/docker.sock',
			process.env.DOCKER_SOCKET
		].filter(Boolean);

		for (const socketPath of socketPaths) {
			if (!socketPath || !existsSync(socketPath)) continue;

			try {
				const info = await new Promise<any>((resolve, reject) => {
					const req = http.request({
						socketPath,
						path: `/containers/${containerId}/json`,
						method: 'GET',
					}, (res) => {
						const chunks: Buffer[] = [];
						res.on('data', (chunk: Buffer) => chunks.push(chunk));
						res.on('end', () => {
							if (res.statusCode === 200) {
								resolve(JSON.parse(Buffer.concat(chunks).toString('utf-8')));
							} else {
								resolve(null);
							}
						});
						res.on('error', () => resolve(null));
					});
					req.on('error', () => resolve(null));
					req.end();
				});

				if (info) {
					return {
						id: info.Id?.slice(0, 12),
						name: info.Name?.replace(/^\//, ''),
						image: info.Config?.Image,
						imageId: info.Image?.slice(7, 19),
						created: info.Created,
						status: info.State?.Status,
						restartCount: info.RestartCount,
						labels: {
							version: info.Config?.Labels?.['org.opencontainers.image.version'],
							revision: info.Config?.Labels?.['org.opencontainers.image.revision']
						}
					};
				}
			} catch {}
		}
	} catch {}

	return null;
}

export const GET: RequestHandler = async ({ url, cookies }) => {
	const auth = await authorize(cookies);

	// Check basic environment view permission
	if (auth.authEnabled && !await auth.can('environments', 'view')) {
		return json({ error: 'Permission denied' }, { status: 403 });
	}

	try {
		const envId = url.searchParams.get('env') ? parseInt(url.searchParams.get('env')!) : null;

		// Check environment access in enterprise mode
		if (envId && auth.authEnabled && auth.isEnterprise && !await auth.canAccessEnvironment(envId)) {
			return json({ error: 'Access denied to this environment' }, { status: 403 });
		}
		const schemaVersion = await getDatabaseSchemaVersion();

		// Try to get Docker info, but don't fail if Docker isn't available
		let dockerInfo = null;
		let dockerVersion = null;
		let connectionInfo = null;
		let containers: any[] = [];
		let images: any[] = [];
		let volumes: any[] = [];
		let networks: any[] = [];

		// Only try Docker connection if environment is specified
		if (envId) {
			try {
				[dockerInfo, dockerVersion, containers, images, volumes, networks, connectionInfo] = await Promise.all([
					getDockerInfo(envId),
					getDockerVersion(envId),
					listContainers(true, envId),
					listImages(envId),
					listVolumes(envId),
					listNetworks(envId),
					getDockerConnectionInfo(envId)
				]);
			} catch (dockerError) {
				// Docker not available - continue with null values
				console.log('Docker not available for system info:', dockerError instanceof Error ? dockerError.message : String(dockerError));
			}
		}

		const stacks = await getStackSources();
		const runningContainers = containers.filter(c => c.state === 'running').length;
		const stoppedContainers = containers.length - runningContainers;

		const runtimeInfo = getRuntimeInfo();
		const containerRuntime = detectContainerRuntime();
		const ownContainer = containerRuntime.inContainer
			? await getOwnContainerInfo(containerRuntime.containerId || os.hostname())
			: null;

		return json({
			docker: dockerInfo && dockerVersion ? {
				version: dockerVersion.Version,
				apiVersion: dockerVersion.ApiVersion,
				os: dockerInfo.OperatingSystem,
				arch: dockerInfo.Architecture,
				kernelVersion: dockerInfo.KernelVersion,
				serverVersion: dockerInfo.ServerVersion,
				connection: connectionInfo ? {
					type: connectionInfo.type,
					socketPath: connectionInfo.socketPath,
					host: connectionInfo.host,
					port: connectionInfo.port
				} : { type: 'socket' }
			} : null,
			host: dockerInfo ? {
				name: dockerInfo.Name,
				cpus: dockerInfo.NCPU,
				memory: dockerInfo.MemTotal,
				storageDriver: dockerInfo.Driver
			} : null,
			runtime: {
				runtimeName: runtimeInfo.name,
				runtimeVersion: runtimeInfo.version,
				nodeVersion: runtimeInfo.version,
				platform: os.platform(),
				arch: os.arch(),
				kernel: os.release(),
				memory: runtimeInfo.memory,
				container: containerRuntime,
				ownContainer
			},
			database: {
				type: isPostgres ? 'PostgreSQL' : 'SQLite',
				schemaVersion: schemaVersion.version,
				schemaDate: schemaVersion.date,
				...(isPostgres && getPostgresConnectionInfo() ? {
					host: getPostgresConnectionInfo()!.host,
					port: getPostgresConnectionInfo()!.port
				} : {})
			},
			stats: {
				containers: {
					total: containers.length,
					running: runningContainers,
					stopped: stoppedContainers
				},
				images: images.length,
				volumes: volumes.length,
				networks: networks.length,
				stacks: stacks.length
			}
		});
	} catch (error) {
		console.error('Error fetching system info:', error);
		return json({ error: 'Failed to fetch system info' }, { status: 500 });
	}
};
