<?php
/**
 * Dashboard Controller
 * Handles dashboard data and statistics for admin interface
 */

class DashboardController {
    private $db;
    private $busModel;
    private $checkinModel;
    private $agentModel;
    private $operatorModel;
    private $lineModel;

    public function __construct($db) {
        $this->db = $db;
        require_once __DIR__ . '/../models/Bus.php';
        require_once __DIR__ . '/../models/Checkin.php';
        require_once __DIR__ . '/../models/Agent.php';
        require_once __DIR__ . '/../models/Operator.php';
        require_once __DIR__ . '/../models/Ligne.php';
        
        $this->busModel = new Bus($this->db);
        $this->checkinModel = new Checkin($this->db);
        $this->agentModel = new Agent($this->db);
        $this->operatorModel = new Operator($this->db);
        $this->lineModel = new Ligne($this->db);
    }

    /**
     * Get general summary statistics
     */
    public function getSummary() {
        Auth::requireAuth();

        $today = date('Y-m-d');
        $yesterday = date('Y-m-d', strtotime('-1 day'));
        $lastWeek = date('Y-m-d', strtotime('-7 days'));

        // Today's statistics
        $todaySummary = $this->checkinModel->getDailySummary($today);
        $yesterdaySummary = $this->checkinModel->getDailySummary($yesterday);

        // Weekly statistics
        $weeklyStats = $this->checkinModel->getStats($lastWeek, $today);

        // General counts
        $totalBuses = count($this->busModel->getAll(['status' => 'Active']));
        $totalAgents = count($this->agentModel->getAll(['is_active' => 1]));
        $totalOperators = count($this->operatorModel->getAll(['statut' => 'actif']));
        $totalLines = count($this->lineModel->getAll(['is_active' => 1]));

        // Calculate percentages
        $checkinPercentage = $totalBuses > 0 ? round(($todaySummary['total_checkins'] / $totalBuses) * 100, 1) : 0;

        $checkinChange = 0;
        if ($yesterdaySummary['total_checkins'] > 0) {
            $checkinChange = round((($todaySummary['total_checkins'] - $yesterdaySummary['total_checkins']) / $yesterdaySummary['total_checkins']) * 100, 1);
        }

        $summary = [
            'today' => [
                'total_checkins' => $todaySummary['total_checkins'] ?? 0,
                'total_agents' => $todaySummary['total_agents'] ?? 0,
                'first_checkin' => $todaySummary['first_checkin'] ?? null,
                'last_checkin' => $todaySummary['last_checkin'] ?? null,
                'avg_checkin_time' => $todaySummary['avg_checkin_time'] ?? null,
                'checkin_percentage' => $checkinPercentage,
                'checkin_change_percentage' => $checkinChange
            ],
            'totals' => [
                'buses' => $totalBuses,
                'agents' => $totalAgents,
                'operators' => $totalOperators,
                'lines' => $totalLines
            ],
            'weekly' => $weeklyStats
        ];

        Auth::sendSuccess($summary, 'Dashboard summary retrieved successfully');
    }

    /**
     * Get daily report for a specific date
     */
    public function getDailyReport($date = null) {
        Auth::requireAuth();

        if (!$date) {
            $date = date('Y-m-d');
        }

        // Validate date format
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
            Auth::sendError('Invalid date format. Use YYYY-MM-DD', 400);
        }

        $dailySummary = $this->checkinModel->getDailySummary($date);
        $hourlyStats = $this->checkinModel->getCheckinsByHour($date);
        $checkedInBuses = $this->busModel->getCheckedInToday($date);
        $absentBuses = $this->busModel->getAbsentToday($date);

        $report = [
            'date' => $date,
            'summary' => $dailySummary,
            'hourly_breakdown' => $hourlyStats,
            'checked_in_buses' => $checkedInBuses,
            'absent_buses' => $absentBuses,
            'checked_in_count' => count($checkedInBuses),
            'absent_count' => count($absentBuses),
            'total_expected' => count($checkedInBuses) + count($absentBuses)
        ];

        Auth::sendSuccess($report, 'Daily report retrieved successfully');
    }

    /**
     * Get absent buses for a specific date
     */
    public function getAbsentBuses($date = null) {
        Auth::requireAuth();

        if (!$date) {
            $date = date('Y-m-d');
        }

        // Validate date format
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
            Auth::sendError('Invalid date format. Use YYYY-MM-DD', 400);
        }

        $absentBuses = $this->busModel->getAbsentToday($date);

        // Group by operator for better organization
        $groupedByOperator = [];
        foreach ($absentBuses as $bus) {
            $operatorName = $bus['operator_name'] ?? 'Unknown';
            if (!isset($groupedByOperator[$operatorName])) {
                $groupedByOperator[$operatorName] = [];
            }
            $groupedByOperator[$operatorName][] = $bus;
        }

        $response = [
            'date' => $date,
            'total_absent' => count($absentBuses),
            'grouped_by_operator' => $groupedByOperator,
            'buses' => $absentBuses
        ];

        Auth::sendSuccess($response, 'Absent buses retrieved successfully');
    }

    /**
     * Get operator performance statistics
     */
    public function getOperatorStats() {
        Auth::requireAuth();

        $dateFrom = $_GET['date_from'] ?? date('Y-m-d', strtotime('-30 days'));
        $dateTo = $_GET['date_to'] ?? date('Y-m-d');

        // Get all operators
        $operators = $this->operatorModel->getAll(['statut' => 1]);

        $operatorStats = [];
        foreach ($operators as $operator) {
            // Count buses for this operator
            $operatorBuses = $this->busModel->getAll([
                'id_operateur' => $operator['id'],
                'actif' => 1
            ]);

            // Count check-ins for this operator's buses in date range
            $checkins = $this->checkinModel->getAll([
                'id_operateur' => $operator['id'],
                'date_from' => $dateFrom,
                'date_to' => $dateTo,
                'is_valid' => 1
            ]);

            $totalBuses = count($operatorBuses);
            $totalCheckins = count($checkins);
            $uniqueDays = count(array_unique(array_column($checkins, 'checkin_date')));

            // Calculate expected check-ins (buses × days)
            $expectedCheckins = $totalBuses * $uniqueDays;

            $operatorStats[] = [
                'operator' => $operator,
                'total_buses' => $totalBuses,
                'total_checkins' => $totalCheckins,
                'expected_checkins' => $expectedCheckins,
                'compliance_percentage' => $expectedCheckins > 0 ? round(($totalCheckins / $expectedCheckins) * 100, 1) : 0,
                'active_days' => $uniqueDays
            ];
        }

        // Sort by compliance percentage descending
        usort($operatorStats, function($a, $b) {
            return $b['compliance_percentage'] <=> $a['compliance_percentage'];
        });

        Auth::sendSuccess($operatorStats, 'Operator statistics retrieved successfully');
    }

    /**
     * Get line performance statistics
     */
    public function getLineStats() {
        Auth::requireAuth();

        $dateFrom = $_GET['date_from'] ?? date('Y-m-d', strtotime('-30 days'));
        $dateTo = $_GET['date_to'] ?? date('Y-m-d');

        // Get all lines
        $lines = $this->lineModel->getAll(['is_active' => 1]);

        $lineStats = [];
        foreach ($lines as $line) {
            // Count buses for this line
            $lineBuses = $this->busModel->getAll([
                'id_ligne' => $line['id'],
                'actif' => 1
            ]);

            // Count check-ins for this line's buses in date range
            $checkins = $this->checkinModel->getAll([
                'id_ligne' => $line['id'],
                'date_from' => $dateFrom,
                'date_to' => $dateTo,
                'is_valid' => 1
            ]);

            $totalBuses = $line['buses_count'];
            $totalCheckins = count($checkins);
            $uniqueDays = count(array_unique(array_column($checkins, 'checkin_date')));

            // Calculate expected check-ins (buses × days)
            $expectedCheckins = $totalBuses * $uniqueDays;

            $lineStats[] = [
                'line' => $line,
                'total_buses' => $totalBuses,
                'total_checkins' => $totalCheckins,
                'expected_checkins' => $expectedCheckins,
                'compliance_percentage' => $expectedCheckins > 0 ? round(($totalCheckins / $expectedCheckins) * 100, 1) : 0,
                'active_days' => $uniqueDays
            ];
        }

        // Sort by compliance percentage descending
        usort($lineStats, function($a, $b) {
            return $b['compliance_percentage'] <=> $a['compliance_percentage'];
        });

        Auth::sendSuccess($lineStats, 'Line statistics retrieved successfully');
    }

    /**
     * Get system health status
     */
    public function getSystemHealth() {
        Auth::requireAdmin();

        $health = [
            'database' => $this->checkDatabaseHealth(),
            'api' => $this->checkApiHealth(),
            'timestamp' => date('Y-m-d H:i:s'),
            'uptime' => $this->getSystemUptime()
        ];

        // Determine overall status
        $overallStatus = 'healthy';
        if (!$health['database']['status'] || !$health['api']['status']) {
            $overallStatus = 'unhealthy';
        }

        $health['overall_status'] = $overallStatus;

        $statusCode = $overallStatus === 'healthy' ? 200 : 503;
        Auth::sendSuccess($health, 'System health check completed', $statusCode);
    }

    /**
     * Check database health
     */
    private function checkDatabaseHealth() {
        try {
            $query = "SELECT 1 as test";
            $stmt = $this->db->prepare($query);
            $stmt->execute();
            $result = $stmt->fetch(PDO::FETCH_ASSOC);

            if ($result && $result['test'] == 1) {
                return ['status' => true, 'message' => 'Database connection successful'];
            } else {
                return ['status' => false, 'message' => 'Database query failed'];
            }
        } catch (Exception $e) {
            return ['status' => false, 'message' => 'Database error: ' . $e->getMessage()];
        }
    }

    /**
     * Check API health
     */
    private function checkApiHealth() {
        // Check if required files exist
        $requiredFiles = [
            'config/Database.php',
            'models/Agent.php',
            'models/Bus.php',
            'models/Checkin.php',
            'controllers/AuthController.php'
        ];

        $missingFiles = [];
        foreach ($requiredFiles as $file) {
            if (!file_exists(__DIR__ . '/../' . $file)) {
                $missingFiles[] = $file;
            }
        }

        if (!empty($missingFiles)) {
            return [
                'status' => false,
                'message' => 'Missing required files: ' . implode(', ', $missingFiles)
            ];
        }

        return ['status' => true, 'message' => 'API files are present and accessible'];
    }

    /**
     * Get system uptime (simplified)
     */
    private function getSystemUptime() {
        // This is a simplified uptime check
        // In a real system, you'd check actual server uptime
        return time() - strtotime('today');
    }

    /**
     * Get alerts for out-of-zone check-ins
     */
    public function getOutOfZoneAlerts() {
        Auth::requireAdmin();

        $date = $_GET['date'] ?? date('Y-m-d');
        $limit = (int)($_GET['limit'] ?? 50);

        // Coordonnées de la gare de Boumerdes (à ajuster selon les vraies coordonnées)
        $stationLat = 36.7667;
        $stationLng = 3.4167;
        $maxDistance = 500; // mètres

        // Récupérer tous les check-ins du jour avec coordonnées GPS
        $allCheckins = $this->checkinModel->getAll([
            'date' => $date,
            'limit' => $limit
        ]);

        $outOfZoneCheckins = [];

        foreach ($allCheckins as $checkin) {
            if (!empty($checkin['latitude']) && !empty($checkin['longitude'])) {
                $distance = $this->calculateDistance(
                    $stationLat,
                    $stationLng,
                    (float)$checkin['latitude'],
                    (float)$checkin['longitude']
                );

                if ($distance > $maxDistance) {
                    $checkin['distance_from_station'] = round($distance, 2);
                    $checkin['station_coordinates'] = ['lat' => $stationLat, 'lng' => $stationLng];
                    $outOfZoneCheckins[] = $checkin;
                }
            }
        }

        $response = [
            'date' => $date,
            'station_location' => [
                'latitude' => $stationLat,
                'longitude' => $stationLng,
                'name' => 'Boumerdes Bus Station'
            ],
            'max_allowed_distance' => $maxDistance,
            'total_out_of_zone' => count($outOfZoneCheckins),
            'alerts' => $outOfZoneCheckins
        ];

        Auth::sendSuccess($response, 'Out-of-zone alerts retrieved successfully');
    }

    /**
     * Calculate distance between two GPS coordinates using Haversine formula
     */
    private function calculateDistance($lat1, $lng1, $lat2, $lng2) {
        $earthRadius = 6371000; // Earth radius in meters

        $latDelta = deg2rad($lat2 - $lat1);
        $lngDelta = deg2rad($lng2 - $lng1);

        $a = sin($latDelta / 2) * sin($latDelta / 2) +
             cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
             sin($lngDelta / 2) * sin($lngDelta / 2);

        $c = 2 * atan2(sqrt($a), sqrt(1 - $a));

        return $earthRadius * $c; // Distance in meters
    }

    /**
     * Get summary with alerts included
     */
    public function getSummaryWithAlerts() {
        Auth::requireAdmin();

        // Get the basic summary
        $this->getSummary();

        // Note: In a real implementation, you'd modify the response to include alerts
        // For now, the alerts endpoint is separate
    }

    /**
     * Get dashboard data for mobile app (simplified stats)
     */
    public function getDashboardData() {
        Auth::requireAuth();

        $date = $_GET['date'] ?? date('Y-m-d');

        // Validate date format
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
            Auth::sendError('Invalid date format. Use YYYY-MM-DD', 400);
        }

        // Get total active buses (actif=1)
        $totalBuses = $this->busModel->getActiveCount();

        // Get scanned buses for the date
        $scannedBuses = $this->checkinModel->getScannedCountForDate($date);

        $data = [
            'date' => $date,
            'total_buses' => $totalBuses,
            'scanned_buses' => $scannedBuses,
            'absent_buses' => $totalBuses - $scannedBuses
        ];

        Auth::sendSuccess($data, 'Dashboard data retrieved successfully');
    }

    /**
     * Export data for reporting
     */
    public function exportData() {
        Auth::requireAdmin();

        $type = $_GET['type'] ?? 'checkins';
        $dateFrom = $_GET['date_from'] ?? date('Y-m-d', strtotime('-30 days'));
        $dateTo = $_GET['date_to'] ?? date('Y-m-d');

        $data = [];

        switch ($type) {
            case 'checkins':
                $data = $this->checkinModel->getAll([
                    'date_from' => $dateFrom,
                    'date_to' => $dateTo
                ]);
                break;

            case 'buses':
                $data = $this->busModel->getAll();
                break;

            case 'agents':
                $data = $this->agentModel->getAll();
                break;

            default:
                Auth::sendError('Invalid export type', 400);
        }

        $export = [
            'type' => $type,
            'date_range' => ['from' => $dateFrom, 'to' => $dateTo],
            'total_records' => count($data),
            'generated_at' => date('Y-m-d H:i:s'),
            'data' => $data
        ];

        Auth::sendSuccess($export, 'Data export generated successfully');
    }
}
?>
