<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\BaseController;
use App\Core\CacheService;
use App\Core\Database;
use App\Core\Rbac;
use App\Core\Request;
use App\Core\Response;
use App\Models\CampaignModel;
use App\Services\PasswordPolicyService;
use App\Services\ReportService;

/**
 * DashboardController
 *
 * The real analytics landing page (Phase 6) — KPI cards, a lead
 * pipeline snapshot, today's/upcoming appointments, and a recent
 * activity feed, every section gated behind the same permission that
 * page's full module requires (a Sales Rep without reports_analytics
 * access still sees their appointments, just not the revenue KPI).
 * Reuses ReportService — the exact same numbers the Reports page and
 * the AI Assistant's generate_report tool produce — cached for 2
 * minutes since this page is the one nearly every session hits first
 * and its numbers don't need to be to-the-second fresh.
 */
final class DashboardController extends BaseController
{
    public function index(Request $request): Response
    {
        $user = $this->currentUser();
        $policy = new PasswordPolicyService();

        $overview = Rbac::can('reports_analytics.view')
            ? CacheService::remember('dashboard:overview', 120, fn () => (new ReportService())->overviewReport(null, 30))
            : null;

        $campaignStats = Rbac::can('email_campaigns.view')
            ? CacheService::remember('dashboard:campaigns', 120, fn () => (new CampaignModel())->dashboardStats())
            : null;

        $upcomingAppointments = Rbac::can('scheduling.view')
            ? CacheService::remember('dashboard:appointments:' . $this->currentUserId(), 60, fn () => $this->fetchUpcomingAppointments())
            : [];

        $recentActivity = Rbac::can('user_management.view')
            ? CacheService::remember('dashboard:activity', 60, fn () => $this->fetchRecentActivity())
            : [];

        return $this->view('dashboard/index', [
            'title' => 'Dashboard',
            'activeNav' => 'dashboard',
            'breadcrumbs' => [['Home', 'dashboard'], ['Dashboard', 'dashboard']],
            'user' => $user,
            'nearingExpiry' => $policy->isNearingExpiry($user['password_changed_at'] ?? null),
            'expiry' => $policy->expiryStatus($user['password_changed_at'] ?? null),
            'overview' => $overview,
            'campaignStats' => $campaignStats,
            'upcomingAppointments' => $upcomingAppointments,
            'recentActivity' => $recentActivity,
        ]);
    }

    private function fetchUpcomingAppointments(): array
    {
        $stmt = Database::connection()->prepare(
            "SELECT a.id, a.scheduled_start, a.status, bl.name AS business_line_name,
                    CONCAT(COALESCE(cu.first_name, l.first_name), ' ', COALESCE(cu.last_name, l.last_name, '')) AS contact_name
             FROM appointments a
             JOIN business_lines bl ON bl.id = a.business_line_id
             LEFT JOIN customers cu ON cu.id = a.customer_id
             LEFT JOIN leads l ON l.id = a.lead_id
             WHERE a.deleted_at IS NULL AND a.status IN ('scheduled','confirmed')
               AND a.scheduled_start BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 7 DAY)
             ORDER BY a.scheduled_start ASC LIMIT 6"
        );
        $stmt->execute();

        return $stmt->fetchAll();
    }

    private function fetchRecentActivity(): array
    {
        $stmt = Database::connection()->prepare(
            "SELECT al.action, al.category, al.created_at, CONCAT(u.first_name, ' ', u.last_name) AS user_name
             FROM activity_logs al
             LEFT JOIN users u ON u.id = al.user_id
             ORDER BY al.created_at DESC LIMIT 8"
        );
        $stmt->execute();

        return $stmt->fetchAll();
    }
}
