import { Application } from 'express';
import { Resource } from 'express-automatic-routes';
import { Req, Res } from '#interfaces/IApi';
import { requireAdminApiKey } from '#middlewares/admin-api-key';
import sequelize from '#services/database/sequelize/sequelizeService';
import RedisService from '#services/storage/redisService';
import { sendSuccess } from '#utils/responseUtils';
import { MultiPoolService } from '#services/database/multiPoolService';

export default (_express: Application) => {
	return <Resource>{
		get: {
			middleware: [requireAdminApiKey],
			handler: async (req: Req, res: Res) => {
				const checks: Record<string, { status: string; latencyMs?: number; error?: string }> = {};

				// PostgreSQL check
				try {
					const start = Date.now();
					await sequelize.authenticate();
					checks.postgresql = { status: 'healthy', latencyMs: Date.now() - start };
				} catch (err: any) {
					checks.postgresql = { status: 'unhealthy', error: err.message };
				}

				// Redis check
				try {
					const redis = RedisService.getInstance();
					const start = Date.now();
					await redis.isRedisConnected();
					checks.redis = { status: 'healthy', latencyMs: Date.now() - start };
				} catch (err: any) {
					checks.redis = { status: 'unhealthy', error: err.message };
				}

				// Project DB pools health
				const poolNames = MultiPoolService.listPools();
				for (const name of poolNames) {
					try {
						const start = Date.now();
						await MultiPoolService.healthCheck(name);
						checks[`pool:${name}`] = { status: 'healthy', latencyMs: Date.now() - start };
					} catch (err: any) {
						checks[`pool:${name}`] = { status: 'unhealthy', error: err.message };
					}
				}

				const allHealthy = Object.values(checks).every((c) => c.status === 'healthy');
				if (allHealthy) {
					return sendSuccess(res, { status: 'healthy', checks, uptime: process.uptime(), timestamp: new Date().toISOString() });
				}
				res.status(503);
				return sendSuccess(res, { status: 'degraded', checks, uptime: process.uptime(), timestamp: new Date().toISOString() });
			},
		},
	};
};
