<?php
declare(strict_types=1);

namespace App\Modules\FacilityGrids\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\FacilityGrids\Models\FacilityGrid;

class GridDashboardController extends Controller
{
    public function index(Request $request): Response
    {
        $this->authorize('facility_grid.view');
        $db = App::getInstance()->db();

        $gridId = (int) ($request->get('grid_id', '0'));
        $filter = $request->get('filter', 'day');
        $from = $request->get('from', date('Y-m-d'));
        $to = $request->get('to', date('Y-m-d'));

        switch ($filter) {
            case 'week':
                $from = date('Y-m-d', strtotime('monday this week'));
                $to = date('Y-m-d', strtotime('sunday this week'));
                break;
            case 'month':
                $from = date('Y-m-01');
                $to = date('Y-m-t');
                break;
            case 'year':
                $from = date('Y-01-01');
                $to = date('Y-12-31');
                break;
            case 'custom':
                $from = $request->get('from', date('Y-m-d'));
                $to = $request->get('to', date('Y-m-d'));
                break;
        }

        $grids = FacilityGrid::allActive();

        $stats = $this->getStats($db, $gridId ?: null, $from, $to);
        $schedulesByDay = $this->getSchedulesByDay($db, $gridId ?: null, $from, $to);
        $occupancyByHour = $this->getOccupancyByHour($db, $gridId ?: null, $from, $to);
        $topCoaches = $this->getTopCoaches($db, $gridId ?: null, $from, $to);

        return $this->view('FacilityGrids.Views.dashboard', [
            'grids'           => $grids,
            'selectedGrid'    => $gridId,
            'filter'          => $filter,
            'from'            => $from,
            'to'              => $to,
            'stats'           => $stats,
            'schedulesByDay'  => $schedulesByDay,
            'occupancyByHour' => $occupancyByHour,
            'topCoaches'      => $topCoaches,
        ]);
    }

    private function getStats($db, ?int $gridId, string $from, string $to): array
    {
        $where = "fzs.is_active = 1 AND fzs.effective_from <= ? AND (fzs.effective_to IS NULL OR fzs.effective_to >= ?)";
        $params = [$to, $from];
        if ($gridId) {
            $where .= " AND fzs.grid_id = ?";
            $params[] = $gridId;
        }

        $totalSchedules = $db->selectOne(
            "SELECT COUNT(*) as cnt FROM facility_zone_schedules fzs WHERE $where",
            $params
        );

        $totalTrainees = $db->selectOne(
            "SELECT COUNT(*) as cnt FROM facility_zone_trainees fzt
             JOIN facility_grid_zones fgz ON fgz.id = fzt.zone_id" .
            ($gridId ? " WHERE fgz.grid_id = ?" : ""),
            $gridId ? [$gridId] : []
        );

        $totalZones = $db->selectOne(
            "SELECT COUNT(*) as cnt FROM facility_grid_zones WHERE is_active = 1" .
            ($gridId ? " AND grid_id = ?" : ""),
            $gridId ? [$gridId] : []
        );

        $occupiedZones = $db->selectOne(
            "SELECT COUNT(DISTINCT CONCAT(fzs.grid_id, ':', fzs.zone_selection_json)) as cnt
             FROM facility_zone_schedules fzs WHERE $where",
            $params
        );

        return [
            'total_schedules' => (int) $totalSchedules['cnt'],
            'total_trainees'  => (int) $totalTrainees['cnt'],
            'total_zones'     => (int) $totalZones['cnt'],
            'occupied_zones'  => (int) $occupiedZones['cnt'],
        ];
    }

    private function getSchedulesByDay($db, ?int $gridId, string $from, string $to): array
    {
        $where = "is_active = 1 AND effective_from <= ? AND (effective_to IS NULL OR effective_to >= ?)";
        $params = [$to, $from];
        if ($gridId) {
            $where .= " AND grid_id = ?";
            $params[] = $gridId;
        }

        return $db->select(
            "SELECT day_of_week, COUNT(*) as cnt FROM facility_zone_schedules WHERE $where GROUP BY day_of_week ORDER BY day_of_week",
            $params
        );
    }

    private function getOccupancyByHour($db, ?int $gridId, string $from, string $to): array
    {
        $where = "is_active = 1 AND effective_from <= ? AND (effective_to IS NULL OR effective_to >= ?)";
        $params = [$to, $from];
        if ($gridId) {
            $where .= " AND grid_id = ?";
            $params[] = $gridId;
        }

        return $db->select(
            "SELECT HOUR(start_time) as hour, COUNT(*) as cnt FROM facility_zone_schedules WHERE $where GROUP BY HOUR(start_time) ORDER BY hour",
            $params
        );
    }

    private function getTopCoaches($db, ?int $gridId, string $from, string $to): array
    {
        $where = "is_active = 1 AND coach_name IS NOT NULL AND coach_name != '' AND effective_from <= ? AND (effective_to IS NULL OR effective_to >= ?)";
        $params = [$to, $from];
        if ($gridId) {
            $where .= " AND grid_id = ?";
            $params[] = $gridId;
        }

        return $db->select(
            "SELECT coach_name, COUNT(*) as sessions FROM facility_zone_schedules WHERE $where GROUP BY coach_name ORDER BY sessions DESC LIMIT 10",
            $params
        );
    }
}
