<?php

class Gameweek extends Model {

    public function calculateAndSetAllDeadlines($league_id, $season_name) {
        // Get all distinct gameweeks for the season/league
        $this->db->query("SELECT DISTINCT gameweek FROM fixtures WHERE league_id = :league_id AND gameweek IS NOT NULL ORDER BY gameweek ASC");
        $this->db->bind(':league_id', $league_id);
        $gameweeks = $this->db->resultSet();

        if (empty($gameweeks)) {
            return false;
        }

        $this->db->beginTransaction();
        try {
            foreach ($gameweeks as $gw) {
                // Find the earliest KICK-OFF time for a SCHEDULED match in this gameweek, ignoring postponed ones.
                $this->db->query("SELECT MIN(match_datetime) as first_match FROM fixtures 
                                  WHERE league_id = :league_id 
                                  AND gameweek = :gameweek 
                                  AND status = 'scheduled'");
                $this->db->bind(':league_id', $league_id);
                $this->db->bind(':gameweek', $gw->gameweek);
                $result = $this->db->single();                

                if ($result && $result->first_match) {
                    // Set deadline 1 hour before the first match
                    $deadline_time = date('Y-m-d H:i:s', strtotime($result->first_match . ' -1 hour'));

                    // Insert or update the deadline
                    $this->db->query("INSERT INTO gameweek_deadlines (league_id, season, gameweek, deadline_time) 
                                      VALUES (:league_id, :season, :gameweek, :deadline)
                                      ON DUPLICATE KEY UPDATE deadline_time = :deadline");
                    $this->db->bind(':league_id', $league_id);
                    $this->db->bind(':season', $season_name);
                    $this->db->bind(':gameweek', $gw->gameweek);
                    $this->db->bind(':deadline', $deadline_time);
                    $this->db->execute();
                }
            }
            $this->db->commit();
            return true;
        } catch (Exception $e) {
            $this->db->rollBack();
            return false;
        }
    }

    public function getDeadlineTime($gameweek, $league_id, $season) {
        $this->db->query("SELECT deadline_time FROM gameweek_deadlines WHERE league_id = :league_id AND season = :season AND gameweek = :gameweek");
        $this->db->bind(':league_id', $league_id);
        $this->db->bind(':season', $season);
        $this->db->bind(':gameweek', $gameweek);
        $result = $this->db->single();
        return $result ? $result->deadline_time : null;
    }

    public function hasDeadlinePassed($gameweek, $league_id, $season) {
        $deadline = $this->getDeadlineTime($gameweek, $league_id, $season);
        if ($deadline) {
            return time() >= strtotime($deadline);
        }
        return false;
    }

    public function resetDeadlines($league_id, $season) {
        $this->db->query("DELETE FROM gameweek_deadlines WHERE league_id = :league_id AND season = :season");
        $this->db->bind(':league_id', $league_id);
        $this->db->bind(':season', $season);
        return $this->db->execute();
    }

    /**
     * Process automatic substitutions for a specific gameweek.
     * Replaces starters who played 0 minutes with valid bench players.
     */
    public function processAutoSubstitutions($gameweek) {
        // 1. Get all fantasy teams that have picks for this gameweek
        // Assuming table 'fantasy_picks' stores the lineup snapshot: (fantasy_team_id, player_id, is_starter, is_captain, etc.)
        // Assuming table 'fantasy_player_stats' stores results: (player_id, gameweek, minutes_played, total_points)
        
        $this->db->query("SELECT DISTINCT fantasy_team_id FROM fantasy_picks WHERE gameweek = :gw");
        $this->db->bind(':gw', $gameweek);
        $teams = $this->db->resultSet();

        if (!$teams) return;

        foreach ($teams as $team) {
            $team_id = $team->fantasy_team_id;

            // Fetch full squad for this team in this gameweek with stats
            $this->db->query("
                SELECT fp.*, p.position, COALESCE(fps.minutes_played, 0) as minutes, COALESCE(fps.total_points, 0) as points
                FROM fantasy_picks fp
                JOIN players p ON fp.player_id = p.id
                LEFT JOIN fantasy_player_stats fps ON fp.player_id = fps.player_id AND fps.gameweek = :gw
                WHERE fp.fantasy_team_id = :tid AND fp.gameweek = :gw
                ORDER BY fp.bench_order ASC
            ");
            $this->db->bind(':gw', $gameweek);
            $this->db->bind(':tid', $team_id);
            $squad = $this->db->resultSet();

            $starters = [];
            $bench = [];
            
            foreach ($squad as $player) {
                if ($player->is_starter) $starters[] = $player;
                else $bench[] = $player;
            }

            // Identify starters who didn't play
            $inactive_starters = array_filter($starters, fn($p) => $p->minutes == 0);

            if (empty($inactive_starters)) continue;

            // Identify active bench players, sorted by points (desc) then bench order (asc)
            $active_bench = array_filter($bench, fn($p) => $p->minutes > 0);
            usort($active_bench, function($a, $b) {
                if ($b->points != $a->points) return $b->points - $a->points; // Highest points first
                return $a->bench_order - $b->bench_order; // Then bench order
            });

            if (empty($active_bench)) continue;

            // Try to swap
            foreach ($inactive_starters as $starter) {
                foreach ($active_bench as $key => $sub) {
                    if ($this->isValidSub($starter, $sub, $starters)) {
                        // Perform Swap in DB
                        $this->performSubstitution($team_id, $gameweek, $starter->player_id, $sub->player_id);
                        
                        // Update local arrays for next iteration
                        $starter->is_starter = 0;
                        $sub->is_starter = 1;
                        // Remove sub from available bench
                        unset($active_bench[$key]);
                        break; // Move to next inactive starter
                    }
                }
            }
        }
    }

    private function isValidSub($starter, $sub, $current_starters) {
        // GK Rule
        if ($starter->position === 'Goalkeeper') return $sub->position === 'Goalkeeper';
        if ($sub->position === 'Goalkeeper') return false; // Cannot sub GK for outfield

        // Formation Rules (Min: 3 DEF, 2 MID, 1 FWD)
        $counts = ['Goalkeeper' => 0, 'Defender' => 0, 'Midfielder' => 0, 'Forward' => 0];
        foreach ($current_starters as $p) {
            if ($p->player_id !== $starter->player_id) $counts[$p->position]++;
        }
        $counts[$sub->position]++; // Add sub

        return ($counts['Defender'] >= 3 && $counts['Midfielder'] >= 2 && $counts['Forward'] >= 1);
    }

    private function performSubstitution($team_id, $gameweek, $starter_id, $sub_id) {
        // Set Starter to Bench
        $this->db->query("UPDATE fantasy_picks SET is_starter = 0, is_auto_sub = 1 WHERE fantasy_team_id = :tid AND player_id = :pid AND gameweek = :gw");
        $this->db->bind(':tid', $team_id); $this->db->bind(':pid', $starter_id); $this->db->bind(':gw', $gameweek);
        $this->db->execute();

        // Set Sub to Starter
        $this->db->query("UPDATE fantasy_picks SET is_starter = 1, is_auto_sub = 1 WHERE fantasy_team_id = :tid AND player_id = :pid AND gameweek = :gw");
        $this->db->bind(':tid', $team_id); $this->db->bind(':pid', $sub_id); $this->db->bind(':gw', $gameweek);
        $this->db->execute();
    }
}