<?php
declare(strict_types=1);

namespace App\Modules\FacilityGrids\Services;

use App\Core\App;
use App\Modules\FacilityGrids\Models\FacilityGrid;
use App\Modules\FacilityGrids\Models\FacilityZoneSchedule;

final class GridStateService
{
    public static function getState(int $gridId, string $date, ?string $time = null): array
    {
        $grid = FacilityGrid::find($gridId);
        if (!$grid) return [];

        $time = $time ?: date('H:i');
        $zones = $grid->getZones();
        $schedules = FacilityZoneSchedule::getActiveForGrid($gridId, $date);

        $db = App::getInstance()->db();
        $trainees = $db->select(
            "SELECT fzt.*, fgz.row_index, fgz.col_index, p.full_name_ar AS player_name
             FROM facility_zone_trainees fzt
             JOIN facility_grid_zones fgz ON fgz.id = fzt.zone_id
             LEFT JOIN players p ON p.id = fzt.player_id
             WHERE fgz.grid_id = ?",
            [$gridId]
        );

        // Build trainee map: "row:col" => [trainees]
        $traineeMap = [];
        foreach ($trainees as $t) {
            $key = $t['row_index'] . ':' . $t['col_index'];
            $traineeMap[$key][] = [
                'id'   => (int) $t['id'],
                'name' => $t['player_name'] ?? $t['trainee_name'] ?? '',
            ];
        }

        // Resolve which zones have active schedules right now
        $zoneStates = [];
        foreach ($zones as $zone) {
            $r = (int) $zone['row_index'];
            $c = (int) $zone['col_index'];
            $key = $r . ':' . $c;

            $activeSchedule = null;
            foreach ($schedules as $sch) {
                if ($sch['start_time'] > $time || $sch['end_time'] <= $time) continue;

                $positions = self::resolvePositions($sch, (int) $grid->rows_count, (int) $grid->cols_count);
                foreach ($positions as $pos) {
                    if ((int) $pos['row'] === $r && (int) $pos['col'] === $c) {
                        $activeSchedule = $sch;
                        break 2;
                    }
                }
            }

            $zoneStates[$key] = [
                'zone_id'      => (int) $zone['id'],
                'row'          => $r,
                'col'          => $c,
                'label'        => $zone['label'] ?? null,
                'max_occupants'=> (int) $zone['max_occupants'],
                'status'       => $activeSchedule ? 'occupied' : 'available',
                'schedule'     => $activeSchedule ? [
                    'id'            => (int) $activeSchedule['id'],
                    'name'          => $activeSchedule['schedule_name'],
                    'activity_type' => $activeSchedule['activity_type'],
                    'coach'         => $activeSchedule['coach_name'] ?? '',
                    'academy'       => $activeSchedule['academy_name'] ?? '',
                    'age_group'     => $activeSchedule['age_group'] ?? '',
                    'gender'        => $activeSchedule['gender'] ?? 'mixed',
                    'color'         => $activeSchedule['color'] ?? '#3B82F6',
                    'time'          => substr($activeSchedule['start_time'], 0, 5) . '–' . substr($activeSchedule['end_time'], 0, 5),
                ] : null,
                'trainees'     => $traineeMap[$key] ?? [],
                'trainee_count'=> count($traineeMap[$key] ?? []),
            ];
        }

        // All schedules for today (for timeline display)
        $todaySchedules = [];
        foreach ($schedules as $sch) {
            $todaySchedules[] = [
                'id'    => (int) $sch['id'],
                'name'  => $sch['schedule_name'],
                'start' => substr($sch['start_time'], 0, 5),
                'end'   => substr($sch['end_time'], 0, 5),
                'color' => $sch['color'] ?? '#3B82F6',
                'coach' => $sch['coach_name'] ?? '',
                'positions' => self::resolvePositions($sch, (int) $grid->rows_count, (int) $grid->cols_count),
            ];
        }

        return [
            'grid_id'    => $gridId,
            'date'       => $date,
            'time'       => $time,
            'rows'       => (int) $grid->rows_count,
            'cols'       => (int) $grid->cols_count,
            'zones'      => $zoneStates,
            'schedules'  => $todaySchedules,
        ];
    }

    public static function resolvePositions(array $schedule, int $totalRows, int $totalCols): array
    {
        $type = $schedule['zone_selection_type'] ?? 'cells';
        $json = json_decode($schedule['zone_selection_json'] ?? '[]', true);
        if (!is_array($json)) return [];

        $positions = [];

        switch ($type) {
            case 'row':
                // New format: array of {row, col} cells — extract unique rows
                if (isset($json[0]['row'])) {
                    $rows = array_unique(array_column($json, 'row'));
                    foreach ($rows as $row) {
                        for ($c = 0; $c < $totalCols; $c++) {
                            $positions[] = ['row' => (int) $row, 'col' => $c];
                        }
                    }
                } else {
                    // Legacy format: {"row": N}
                    $row = (int) ($json['row'] ?? 0);
                    for ($c = 0; $c < $totalCols; $c++) {
                        $positions[] = ['row' => $row, 'col' => $c];
                    }
                }
                break;

            case 'column':
                // New format: array of {row, col} cells — extract unique cols
                if (isset($json[0]['row'])) {
                    $cols = array_unique(array_column($json, 'col'));
                    foreach ($cols as $col) {
                        for ($r = 0; $r < $totalRows; $r++) {
                            $positions[] = ['row' => $r, 'col' => (int) $col];
                        }
                    }
                } else {
                    // Legacy format: {"col": N}
                    $col = (int) ($json['col'] ?? 0);
                    for ($r = 0; $r < $totalRows; $r++) {
                        $positions[] = ['row' => $r, 'col' => $col];
                    }
                }
                break;

            case 'all':
                for ($r = 0; $r < $totalRows; $r++) {
                    for ($c = 0; $c < $totalCols; $c++) {
                        $positions[] = ['row' => $r, 'col' => $c];
                    }
                }
                break;

            default: // cells
                foreach ($json as $cell) {
                    if (isset($cell['row'], $cell['col'])) {
                        $positions[] = ['row' => (int) $cell['row'], 'col' => (int) $cell['col']];
                    }
                }
                break;
        }

        return $positions;
    }

    public static function checkConflicts(int $gridId, array $positions, int $dayOfWeek, string $startTime, string $endTime, string $effectiveFrom, ?string $effectiveTo = null, ?int $excludeScheduleId = null): array
    {
        $db = App::getInstance()->db();
        $grid = FacilityGrid::find($gridId);
        if (!$grid) return [];

        $query = "SELECT * FROM facility_zone_schedules
                  WHERE grid_id = ? AND day_of_week = ? AND is_active = 1
                  AND start_time < ? AND end_time > ?
                  AND effective_from <= ? AND (effective_to IS NULL OR effective_to >= ?)";
        $params = [$gridId, $dayOfWeek, $endTime, $startTime, $effectiveTo ?: '9999-12-31', $effectiveFrom];

        if ($excludeScheduleId) {
            $query .= " AND id != ?";
            $params[] = $excludeScheduleId;
        }

        $existing = $db->select($query, $params);

        $conflicts = [];
        foreach ($existing as $sch) {
            $schPositions = self::resolvePositions($sch, (int) $grid->rows_count, (int) $grid->cols_count);
            $overlap = [];
            foreach ($positions as $pos) {
                foreach ($schPositions as $sp) {
                    if ((int) $pos['row'] === (int) $sp['row'] && (int) $pos['col'] === (int) $sp['col']) {
                        $overlap[] = $pos;
                    }
                }
            }
            if (!empty($overlap)) {
                $conflicts[] = [
                    'schedule_id'   => (int) $sch['id'],
                    'schedule_name' => $sch['schedule_name'],
                    'time'          => substr($sch['start_time'], 0, 5) . '–' . substr($sch['end_time'], 0, 5),
                    'overlap_zones' => $overlap,
                ];
            }
        }

        return $conflicts;
    }
}
