/**
 * IP Analytics Routes
 * Hanya pencatatan: IP yang bisa/tidak bisa akses (connection_attempts, isp_statistics).
 * Bukan untuk block maupun whitelist.
 */

const express = require('express');
const router = express.Router();
const IPAnalyticsService = require('./ip-analytics.service');

/**
 * Cek apakah error disebabkan tabel belum ada / model belum siap
 */
function isIPTablesMissingOrNotReady(err) {
	if (!err) return false;
	const msg = String(err.message || '').toLowerCase();
	const code = err.original?.code || err.code || '';
	return (
		code === 'ER_NO_SUCH_TABLE' ||
		code === 'TABLES_MISSING' ||
		msg.includes("doesn't exist") ||
		msg.includes("does not exist") ||
		(msg.includes('connection_attempts') && msg.includes('exist')) ||
		(msg.includes('findall') && msg.includes('undefined'))
	);
}

/**
 * Cek apakah error disebabkan connection manager sudah ditutup
 */
function isConnectionClosed(err) {
	if (!err) return false;
	const msg = String(err.message || '').toLowerCase();
	const code = err.code || '';
	return (
		code === 'CONNECTION_CLOSED' ||
		msg.includes('connection manager was closed') ||
		msg.includes('connection manager is closed') ||
		msg.includes('connectionmanager.getconnection was called after')
	);
}

/**
 * Kirim respons error yang konsisten; 503 bila tabel belum ada atau connection closed
 */
function handleIPAnalyticsError(res, err, humanError) {
	if (isIPTablesMissingOrNotReady(err)) {
		return res.status(503).json({
			success: false,
			error: 'IP Analytics not configured',
			message: 'Tabel analisa IP belum tersedia. Jalankan migrasi: npx sequelize-cli db:migrate',
			code: 'TABLES_MISSING',
		});
	}
	
	if (isConnectionClosed(err)) {
		return res.status(503).json({
			success: false,
			error: 'Database connection unavailable',
			message: 'Database connection manager is closed. System may be shutting down or connection lost. Please try again later.',
			code: 'CONNECTION_CLOSED',
		});
	}
	
	console.error('[IP Analytics]', humanError, err);
	res.status(500).json({
		success: false,
		error: humanError,
		message: err?.message || 'Unknown error',
	});
}

/**
 * @route   GET /api/ip-analytics/connection-attempts
 * @desc    Get connection attempts with filtering
 * @access  Private (Admin only)
 * @query   isp, status, startDate, endDate, limit, offset, ip
 */
router.get('/connection-attempts', async (req, res) => {
	try {
		const options = {
			isp: req.query.isp,
			status: req.query.status,
			startDate: req.query.startDate,
			endDate: req.query.endDate,
			limit: req.query.limit || 100,
			offset: req.query.offset || 0,
			ip: req.query.ip,
		};

		const result = await IPAnalyticsService.getConnectionAttempts(options);

		res.json({
			success: true,
			...result,
		});
	} catch (error) {
		handleIPAnalyticsError(res, error, 'Failed to fetch connection attempts');
	}
});

/**
 * @route   GET /api/ip-analytics/isp-statistics
 * @desc    Get ISP statistics
 * @access  Private (Admin only)
 * @query   sortBy, order
 */
router.get('/isp-statistics', async (req, res) => {
	try {
		const sortBy = req.query.sortBy || 'total_attempts';
		const order = req.query.order || 'DESC';

		const statistics = await IPAnalyticsService.getISPStatistics(sortBy, order);

		res.json({
			success: true,
			data: statistics,
			count: statistics.length,
		});
	} catch (error) {
		handleIPAnalyticsError(res, error, 'Failed to fetch ISP statistics');
	}
});

/**
 * @route   GET /api/ip-analytics/connection-heatmap
 * @desc    Get connection heatmap data (time-based)
 * @access  Private (Admin only)
 * @query   days, isp
 */
router.get('/connection-heatmap', async (req, res) => {
	try {
		const options = {
			days: parseInt(req.query.days) || 7,
			isp: req.query.isp,
		};

		const heatmap = await IPAnalyticsService.getConnectionHeatmap(options);

		res.json({
			success: true,
			data: heatmap,
			count: heatmap.length,
		});
	} catch (error) {
		handleIPAnalyticsError(res, error, 'Failed to fetch connection heatmap');
	}
});

/**
 * @route   GET /api/ip-analytics/failing-endpoints
 * @desc    Get top failing endpoints
 * @access  Private (Admin only)
 * @query   limit
 */
router.get('/failing-endpoints', async (req, res) => {
	try {
		const limit = parseInt(req.query.limit) || 10;
		const endpoints = await IPAnalyticsService.getTopFailingEndpoints(limit);

		res.json({
			success: true,
			data: endpoints,
			count: endpoints.length,
		});
	} catch (error) {
		handleIPAnalyticsError(res, error, 'Failed to fetch failing endpoints');
	}
});

/**
 * @route   GET /api/ip-analytics/recent-failures
 * @desc    Get recent connection failures (real-time monitoring)
 * @access  Private (Admin only)
 * @query   minutes, limit
 */
router.get('/recent-failures', async (req, res) => {
	try {
		const minutes = parseInt(req.query.minutes) || 15;
		const limit = parseInt(req.query.limit) || 50;

		const failures = await IPAnalyticsService.getRecentFailures(minutes, limit);

		res.json({
			success: true,
			data: failures,
			count: failures.length,
			timeWindow: `${minutes} minutes`,
		});
	} catch (error) {
		handleIPAnalyticsError(res, error, 'Failed to fetch recent failures');
	}
});

/**
 * @route   GET /api/ip-analytics/isp-comparison
 * @desc    Generate comprehensive ISP comparison report
 * @access  Private (Admin only)
 */
router.get('/isp-comparison', async (req, res) => {
	try {
		const comparison = await IPAnalyticsService.generateISPComparison();

		res.json({
			success: true,
			...comparison,
		});
	} catch (error) {
		handleIPAnalyticsError(res, error, 'Failed to generate ISP comparison');
	}
});

/**
 * @route   GET /api/ip-analytics/export-csv
 * @desc    Export connection data to CSV
 * @access  Private (Admin only)
 * @query   isp, status, startDate, endDate
 */
router.get('/export-csv', async (req, res) => {
	try {
		const options = {
			isp: req.query.isp,
			status: req.query.status,
			startDate: req.query.startDate,
			endDate: req.query.endDate,
		};

		const csv = await IPAnalyticsService.exportToCSV(options);

		// Set headers for CSV download
		res.setHeader('Content-Type', 'text/csv');
		res.setHeader('Content-Disposition', `attachment; filename=connection-attempts-${Date.now()}.csv`);

		res.send(csv);
	} catch (error) {
		handleIPAnalyticsError(res, error, 'Failed to export CSV');
	}
});

/**
 * @route   GET /api/ip-analytics/summary
 * @desc    Get quick summary of connection tracking
 * @access  Private (Admin only)
 */
router.get('/summary', async (req, res) => {
	try {
		const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);

		const [totalStats, recentFailures, topISPs] = await Promise.all([
			IPAnalyticsService.getConnectionAttempts({
				startDate: oneDayAgo,
				limit: 1,
			}),
			IPAnalyticsService.getRecentFailures(60, 10),
			IPAnalyticsService.getISPStatistics('total_attempts', 'DESC'),
		]);

		res.json({
			success: true,
			summary: {
				last_24h_total: totalStats.total,
				recent_failures_count: recentFailures.length,
				total_isps_tracked: topISPs.length,
				top_isps: topISPs.slice(0, 5),
			},
		});
	} catch (error) {
		handleIPAnalyticsError(res, error, 'Failed to fetch summary');
	}
});

/**
 * @route   GET /api/ip-analytics/top-database-failure-ips
 * @desc    Get top N IPs that failed database connections
 * @access  Private (Admin only)
 * @query   limit (default: 10)
 */
router.get('/top-database-failure-ips', async (req, res) => {
	try {
		const limit = parseInt(req.query.limit) || 10;
		const topIPs = await IPAnalyticsService.getTopDatabaseFailureIPs(limit);

		res.json({
			success: true,
			data: topIPs,
			count: topIPs.length,
			timestamp: new Date().toISOString(),
		});
	} catch (error) {
		handleIPAnalyticsError(res, error, 'Failed to fetch top database failure IPs');
	}
});

module.exports = router;
