import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { getDockerInfo, getHawserInfo } from '$lib/server/docker';
import { getEnvironment } from '$lib/server/db';
import { authorize } from '$lib/server/authorize';
import { getEdgeConnectionInfo } from '$lib/server/hawser';
import os from 'node:os';

export interface HostInfo {
	hostname: string;
	ipAddress: string;
	platform: string;
	arch: string;
	cpus: number;
	totalMemory: number;
	freeMemory: number;
	uptime: number;
	dockerVersion: string;
	dockerContainers: number;
	dockerContainersRunning: number;
	dockerImages: number;
	environment: {
		id: number;
		name: string;
		icon?: string;
		socketPath?: string;
		connectionType?: string;
		hawserVersion?: string;
		highlightChanges?: boolean;
	};
}

function getLocalIpAddress(): string {
	const interfaces = os.networkInterfaces();
	for (const name of Object.keys(interfaces)) {
		const netInterface = interfaces[name];
		if (!netInterface) continue;
		for (const net of netInterface) {
			// Skip internal and non-IPv4 addresses
			if (!net.internal && net.family === 'IPv4') {
				return net.address;
			}
		}
	}
	return '127.0.0.1';
}

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 {
		// Get environment ID from query param, or use default
		const envIdParam = url.searchParams.get('env');
		let env;

		if (envIdParam) {
			const envId = parseInt(envIdParam);
			// Check if user can access this specific environment
			if (auth.authEnabled && auth.isEnterprise && !await auth.canAccessEnvironment(envId)) {
				return json({ error: 'Access denied to this environment' }, { status: 403 });
			}
			env = await getEnvironment(envId);
		}

		if (!env) {
			// No environment specified - return basic local info
			return json({
				hostname: os.hostname(),
				ipAddress: getLocalIpAddress(),
				platform: os.platform(),
				arch: os.arch(),
				cpus: os.cpus().length,
				totalMemory: os.totalmem(),
				freeMemory: os.freemem(),
				uptime: os.uptime(),
				dockerVersion: null,
				dockerContainers: 0,
				dockerContainersRunning: 0,
				dockerImages: 0,
				environment: null
			});
		}

		// Determine if this is a truly local connection (socket without remote host)
		const isSocketType = env.connectionType === 'socket' || !env.connectionType;
		const isLocalConnection = isSocketType && (!env.host || env.host === 'localhost' || env.host === '127.0.0.1');

		// Fetch Docker info and Hawser info in parallel for hawser-standard mode
		let dockerInfo: any;
		let uptime = 0;
		let hawserVersion: string | undefined;

		if (env.connectionType === 'hawser-standard') {
			// Parallel fetch for hawser-standard
			const [dockerResult, hawserInfo] = await Promise.all([
				getDockerInfo(env.id),
				getHawserInfo(env.id)
			]);
			dockerInfo = dockerResult;
			if (hawserInfo?.uptime) {
				uptime = hawserInfo.uptime;
			}
			if (hawserInfo?.hawserVersion) {
				hawserVersion = hawserInfo.hawserVersion;
			}
		} else {
			// Sequential for other connection types
			dockerInfo = await getDockerInfo(env.id);

			if (isLocalConnection) {
				uptime = os.uptime();
			} else if (env.connectionType === 'hawser-edge') {
				// For Hawser edge mode, get from edge connection metrics (sync lookup)
				const edgeConn = getEdgeConnectionInfo(env.id);
				if (edgeConn?.lastMetrics?.uptime) {
					uptime = edgeConn.lastMetrics.uptime;
				}
			}
			// For 'direct' connections without Hawser, uptime remains 0 (not available)
		}

		const hostInfo: HostInfo = {
			// For local connections, show local system info; for remote, show Docker host info
			hostname: isLocalConnection ? os.hostname() : (dockerInfo.Name || env.host || 'unknown'),
			ipAddress: isLocalConnection ? getLocalIpAddress() : (env.host || 'unknown'),
			platform: isLocalConnection ? os.platform() : (dockerInfo.OperatingSystem || 'unknown'),
			arch: isLocalConnection ? os.arch() : (dockerInfo.Architecture || 'unknown'),
			cpus: isLocalConnection ? os.cpus().length : (dockerInfo.NCPU || 0),
			totalMemory: isLocalConnection ? os.totalmem() : (dockerInfo.MemTotal || 0),
			freeMemory: isLocalConnection ? os.freemem() : 0, // Not available from Docker API
			uptime,
			dockerVersion: dockerInfo.ServerVersion || 'unknown',
			dockerContainers: dockerInfo.Containers || 0,
			dockerContainersRunning: dockerInfo.ContainersRunning || 0,
			dockerImages: dockerInfo.Images || 0,
			environment: {
				id: env.id,
				name: env.name,
				icon: env.icon,
				socketPath: env.socketPath,
				connectionType: env.connectionType || 'socket',
				// For standard mode, use live-fetched version; for edge mode, use stored version
				hawserVersion: hawserVersion || env.hawserVersion,
				highlightChanges: env.highlightChanges
			}
		};

		return json(hostInfo);
	} catch (error) {
		console.error('Failed to get host info:', error);
		return json({ error: 'Failed to get host info' }, { status: 500 });
	}
};
