<?php

namespace App\Controllers;

use App\Controllers\BaseController;
use App\Models\CompanyModel;
use App\Models\PersonnelModel;
use App\Models\UserModel;
use App\Models\ContractorModel;
use CodeIgniter\HTTP\ResponseInterface;

class Dashboard extends BaseController
{
    protected $companyModel;
    protected $personnelModel;
    protected $userModel;
    protected $contractorModel;

    public function __construct()
    {
        $this->companyModel = new CompanyModel();
        $this->personnelModel = new PersonnelModel();
        $this->userModel = new UserModel();
        $this->contractorModel = new ContractorModel();
    }

    /**
     * Display the dashboard
     *
     * @return string
     */
    public function index()
    {
        // Check if user is logged in
        if (!session()->get('isLoggedIn')) {
            return redirect()->to('/login');
        }

        // Get page number from request, default to 1
        $page = $this->request->getGet('page') ?? 1;
        $perPage = 5; // Number of activities per page

        // Fetch real statistics
        $data['stats'] = [
            'total_companies' => $this->companyModel->where('deleted_at', null)->countAllResults(),
            'active_companies' => $this->companyModel->where('deleted_at', null)->where('status', 'Active')->countAllResults(),
            'total_personnel' => $this->personnelModel->where('deleted_at', null)->countAllResults(),
            'active_personnel' => $this->personnelModel->where('deleted_at', null)->where('status', 'Active')->countAllResults(),
            'total_contractors' => $this->contractorModel->getTotalContractors(),
        ];

        // For superadmin, also fetch admin count
        if (session()->get('role') === 'superadmin') {
            $data['stats']['total_admins'] = $this->userModel->where('role', 'admin')->countAllResults();
        }

        // Fetch additional statistics
        $companyStats = $this->companyModel->getCompanyStats();
        $personnelStats = $this->personnelModel->getPersonnelStats();
        
        // Merge additional statistics
        $data['stats'] = array_merge($data['stats'], $companyStats, $personnelStats);
        
        // Fetch recent companies and personnel
        $data['recent_companies'] = $this->companyModel->getRecentCompanies(5);
        $data['recent_personnel'] = $this->personnelModel->getRecentPersonnel(5);
        
        // Fetch recent activity with pagination
        $activityData = $this->getRecentActivity($perPage, $page);
        $data['recent_activity'] = $activityData['activities'];
        $data['pager'] = $activityData['pager'];
        $data['currentPage'] = $page;
        $data['perPage'] = $perPage;
        
        // Fetch companies by area for chart
        $data['companies_by_area'] = $this->getCompaniesByArea();
        
        // Fetch personnel by status
        $data['personnel_by_status'] = $this->getPersonnelByStatus();
        
        // Fetch system status information
        $data['system_status'] = $this->getSystemStatus();
        
        // Fetch user's last login time
        $userId = session()->get('user_id');
        $user = $this->userModel->find($userId);
        if ($user && !empty($user['last_login'])) {
            $data['system_status']['last_login'] = $user['last_login'];
        }

        // Fetch notifications (in a real app, this would come from a notifications table)
        $data['notifications'] = $this->getNotifications();

        return view('dashboard_content', $data);
    }
    
    /**
     * Get system status information
     *
     * @return array
     */
    private function getSystemStatus()
    {
        // Database status
        $dbStatus = 'Online';
        $dbError = false;
        
        try {
            // Test database connection
            $db = \Config\Database::connect();
            $db->query('SELECT 1');
        } catch (\Exception $e) {
            $dbStatus = 'Offline';
            $dbError = true;
        }
        
        // Storage usage (simplified)
        $storageTotal = disk_total_space('.');
        $storageFree = disk_free_space('.');
        $storageUsed = $storageTotal - $storageFree;
        $storagePercentage = $storageTotal > 0 ? round(($storageUsed / $storageTotal) * 100) : 0;
        
        // Backup status (check if backup file exists and is recent)
        $backupStatus = 'Not Available';
        $backupPath = WRITEPATH . 'backups/';
        if (is_dir($backupPath)) {
            $files = glob($backupPath . '*.sql');
            if (!empty($files)) {
                $latestBackup = max($files);
                $backupTime = filemtime($latestBackup);
                $daysSinceBackup = (time() - $backupTime) / (60 * 60 * 24);
                
                if ($daysSinceBackup <= 1) {
                    $backupStatus = 'Up to date';
                } elseif ($daysSinceBackup <= 7) {
                    $backupStatus = 'Recent';
                } else {
                    $backupStatus = 'Outdated';
                }
            }
        }
        
        return [
            'database' => [
                'status' => $dbStatus,
                'error' => $dbError
            ],
            'storage' => [
                'used' => $this->formatBytes($storageUsed),
                'total' => $this->formatBytes($storageTotal),
                'percentage' => $storagePercentage
            ],
            'backup' => [
                'status' => $backupStatus
            ]
        ];
    }
    
    /**
     * Format bytes to human readable format
     *
     * @param int $bytes
     * @param int $precision
     * @return string
     */
    private function formatBytes($bytes, $precision = 2)
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        
        for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
            $bytes /= 1024;
        }
        
        return round($bytes, $precision) . ' ' . $units[$i];
    }
    
    /**
     * Get recent activity combining companies and personnel with pagination
     *
     * @param int $perPage
     * @param int $page
     * @return array
     */
    private function getRecentActivity($perPage = 5, $page = 1)
    {
        // Calculate offset
        $offset = ($page - 1) * $perPage;
        
        // Get recent companies
        $recentCompanies = $this->companyModel->select('id, company_name as title, created_at, "company" as type')
            ->where('deleted_at', null)
            ->orderBy('created_at', 'DESC')
            ->findAll();
            
        // Get recent personnel
        $recentPersonnel = $this->personnelModel->select('personnel.id, personnel.name as title, personnel.created_at, "personnel" as type, companies.company_name')
            ->join('companies', 'companies.id = personnel.company_id', 'left')
            ->where('personnel.deleted_at', null)
            ->orderBy('personnel.created_at', 'DESC')
            ->findAll();
            
        // Format the activity data
        $activity = [];
        
        // Format companies activity
        foreach ($recentCompanies as $company) {
            $activity[] = [
                'id' => $company['id'],
                'title' => 'New Company Registered',
                'message' => $company['title'] . ' was added to the system',
                'timestamp' => $company['created_at'],
                'time_ago' => $this->timeElapsedString($company['created_at']),
                'type' => 'company',
                'icon' => 'fa-building',
                'icon_class' => 'bg-primary',
                'text_class' => 'text-primary'
            ];
        }
        
        // Format personnel activity
        foreach ($recentPersonnel as $person) {
            $activity[] = [
                'id' => $person['id'],
                'title' => 'New Employee Added',
                'message' => $person['title'] . ' was added to ' . ($person['company_name'] ?? 'the system'),
                'timestamp' => $person['created_at'],
                'time_ago' => $this->timeElapsedString($person['created_at']),
                'type' => 'personnel',
                'icon' => 'fa-user-plus',
                'icon_class' => 'bg-success',
                'text_class' => 'text-success'
            ];
        }
        
        // Sort by timestamp (newest first)
        usort($activity, function($a, $b) {
            return strtotime($b['timestamp']) - strtotime($a['timestamp']);
        });
        
        // Get total count for pagination
        $totalCount = count($activity);
        
        // Apply pagination
        $paginatedActivity = array_slice($activity, $offset, $perPage);
        
        // Create pager data
        $pager = [
            'total' => $totalCount,
            'perPage' => $perPage,
            'currentPage' => $page,
            'totalPages' => ceil($totalCount / $perPage),
            'hasNext' => $page < ceil($totalCount / $perPage),
            'hasPrevious' => $page > 1
        ];
        
        return [
            'activities' => $paginatedActivity,
            'pager' => $pager
        ];
    }
    
    /**
     * Get notifications data for AJAX requests
     *
     * @return ResponseInterface
     */
    public function getNotificationsData()
    {
        $notifications = $this->getNotifications();
        $unreadCount = 0;
        
        foreach ($notifications as $notification) {
            if (!$notification['read']) {
                $unreadCount++;
            }
        }
        
        return $this->response->setJSON([
            'notifications' => $notifications,
            'unreadCount' => $unreadCount
        ]);
    }
    
    /**
     * Get companies grouped by area
     *
     * @return array
     */
    private function getCompaniesByArea()
    {
        $builder = $this->companyModel->builder();
        $builder->select('area, COUNT(*) as count');
        $builder->where('deleted_at', null);
        $builder->groupBy('area');
        $builder->orderBy('count', 'DESC');
        return $builder->get()->getResultArray();
    }
    
    /**
     * Get personnel grouped by status
     *
     * @return array
     */
    private function getPersonnelByStatus()
    {
        $builder = $this->personnelModel->builder();
        $builder->select('status, COUNT(*) as count');
        $builder->where('deleted_at', null);
        $builder->groupBy('status');
        return $builder->get()->getResultArray();
    }
    
    /**
     * Get notifications for the user
     *
     * @return array
     */
    private function getNotifications()
    {
        // In a real application, this would fetch from a notifications table
        // For now, we'll generate sample notifications based on recent activity
        $notifications = [];
        
        // Get recent companies for company-related notifications
        $recentCompanies = $this->companyModel->select('company_name, created_at')
            ->where('deleted_at', null)
            ->orderBy('created_at', 'DESC')
            ->limit(3)
            ->findAll();
            
        // Get recent personnel for personnel-related notifications
        $recentPersonnel = $this->personnelModel->select('name, created_at')
            ->where('deleted_at', null)
            ->orderBy('created_at', 'DESC')
            ->limit(3)
            ->findAll();
            
        // Generate company notifications
        foreach ($recentCompanies as $index => $company) {
            $notifications[] = [
                'id' => $index + 1,
                'title' => 'New Company Added',
                'message' => $company['company_name'] . ' has been added to the system',
                'timestamp' => $this->timeElapsedString($company['created_at']),
                'read' => false,
                'type' => 'company'
            ];
        }
        
        // Generate personnel notifications
        foreach ($recentPersonnel as $index => $person) {
            $notifications[] = [
                'id' => $index + 4,
                'title' => 'New Employee Added',
                'message' => $person['name'] . ' has been added to the system',
                'timestamp' => $this->timeElapsedString($person['created_at']),
                'read' => false,
                'type' => 'personnel'
            ];
        }
        
        // Add system notifications
        $notifications[] = [
            'id' => 7,
            'title' => 'Welcome Back',
            'message' => 'Welcome back, ' . session()->get('username') . '! Have a great day.',
            'timestamp' => 'Just now',
            'read' => false,
            'type' => 'system'
        ];
        
        // Sort by timestamp (newest first)
        usort($notifications, function($a, $b) {
            return strtotime($b['timestamp']) - strtotime($a['timestamp']);
        });
        
        // Limit to 5 most recent notifications
        return array_slice($notifications, 0, 5);
    }
    
    /**
     * Convert datetime to human-readable format
     *
     * @param string $datetime
     * @return string
     */
    private function timeElapsedString($datetime)
    {
        $now = new \DateTime();
        $ago = new \DateTime($datetime);
        $diff = $now->diff($ago);
        
        if ($diff->days > 0) {
            return $diff->days . ' day' . ($diff->days > 1 ? 's' : '') . ' ago';
        } elseif ($diff->h > 0) {
            return $diff->h . ' hour' . ($diff->h > 1 ? 's' : '') . ' ago';
        } elseif ($diff->i > 0) {
            return $diff->i . ' minute' . ($diff->i > 1 ? 's' : '') . ' ago';
        } else {
            return 'Just now';
        }
    }
    
    /**
     * Handle search requests
     *
     * @return string
     */
    public function search()
    {
        $searchTerm = $this->request->getGet('q');
        
        if (empty($searchTerm)) {
            return $this->response->setJSON(['results' => []]);
        }
        
        // Search companies
        $companies = $this->companyModel
            ->select('id, company_name as name, "company" as type, created_at')
            ->like('company_name', $searchTerm)
            ->where('deleted_at', null)
            ->limit(5)
            ->findAll();
            
        // Search personnel
        $personnel = $this->personnelModel
            ->select('id, name, "personnel" as type, created_at')
            ->like('name', $searchTerm)
            ->where('deleted_at', null)
            ->limit(5)
            ->findAll();
            
        // Combine results
        $results = array_merge($companies, $personnel);
        
        // Sort by created_at (newest first)
        usort($results, function($a, $b) {
            return strtotime($b['created_at']) - strtotime($a['created_at']);
        });
        
        // Limit to 10 results
        $results = array_slice($results, 0, 10);
        
        return $this->response->setJSON(['results' => $results]);
    }
    
    /**
     * Mark notifications as read
     *
     * @return ResponseInterface
     */
    public function markNotificationsAsRead()
    {
        // In a real application, this would update the notifications table
        // For now, we'll just return success
        return $this->response->setJSON(['success' => true]);
    }
    
    /**
     * Display all notifications page
     *
     * @return string
     */
    public function notifications()
    {
        return view('notifications');
    }
    
    /**
     * Display debug information
     *
     * @return string
     */
    public function debug()
    {
        // Check if user is logged in
        if (!session()->get('isLoggedIn')) {
            return redirect()->to('/login');
        }

        return view('debug');
    }
}