<?php

namespace App\Livewire;

use App\Models\Event;
use App\Models\Hud;
use App\Models\Inscription;
use App\Models\Modality;
use App\Models\Round;
use App\Models\RoundBuffer;
use Illuminate\Support\Facades\Log;
use Livewire\Attributes\On;
use Livewire\Component;

class ShowHud extends Component
{
    public $event;
    public $inscriptions;
    public $modality;
    public $rounds;
    public $currentRoundValue;
    public $modalityId;
    public $eventId;
    public $finalRound;
    public $group;
    public $viewportStartIndex = 0;
    public $lastTriggerSignature = null;

    public function mount()
    {
        $this->modality = null;
        $this->event = null;
        $this->currentRoundValue = null;
        $this->group = null;
        $this->viewportStartIndex = 0;

        // Validate and load modality from query parameters
        if (request()->has('modality')) {
            $modalityParam = request()->get('modality');
            $modalityId = filter_var($modalityParam, FILTER_VALIDATE_INT);

            if ($modalityId !== false && $modalityId > 0) {
                $modalityModel = Modality::find($modalityId);

                if ($modalityModel) {
                    $this->modality = $modalityId;
                    $this->group = $modalityModel->active_additional_rules ? 'classification' : null;

                    Log::info('ShowHud mounted - Modality found', [
                        'modality_id' => $modalityId,
                        'modality_name' => $modalityModel->name,
                    ]);
                } else {
                    Log::warning('ShowHud mounted - Modality not found', [
                        'requested_modality_id' => $modalityId,
                    ]);
                }
            } else {
                Log::warning('ShowHud mounted - Invalid modality parameter', [
                    'modality_param' => $modalityParam,
                ]);
            }
        }

        if (request()->has('event')) {
            $eventParam = request()->get('event');
            $eventId = filter_var($eventParam, FILTER_VALIDATE_INT);

            if ($eventId !== false && $eventId > 0) {
                $this->eventId = $eventId;
            }
        }

        if (request()->has('current')) {
            $currentParam = request()->get('current');
            $current = filter_var($currentParam, FILTER_VALIDATE_INT);

            if ($current !== false && $current > 0) {
                $this->currentRoundValue = $current;
            }
        }

        if (request()->has('final')) {
            $finalParam = request()->get('final');
            $final = filter_var($finalParam, FILTER_VALIDATE_INT);

            if ($final !== false && $final > 0) {
                $this->finalRound = $final;
            }
        }

        if (request()->has('group')) {
            $groupParam = request()->get('group');
            $this->group = ($groupParam === '' || $groupParam === 'null') ? null : $groupParam;
        }

        // Se não houver parâmetro de modalidade, busca automaticamente
        if (!$this->modality) {
            $this->loadActiveOrFinalizedModality();
        }

        Log::info('ShowHud mounted', [
            'modality' => $this->modality,
            'event' => $this->eventId,
            'currentRound' => $this->currentRoundValue,
            'finalRound' => $this->finalRound,
            'group' => $this->group,
        ]);
    }

    #[On('echo:world-rodeo,HudEvent')]
    public function handleHudEvent(array $payload)
    {
        $modalityId = $payload['modalityId'] ?? null;

        if ($modalityId && Modality::find($modalityId)) {
            $this->modality = $modalityId;
            $this->currentRoundValue = $payload['currentStep'] ?? null;
            $this->finalRound = $payload['finalStep'] ?? null;

            $modalityModel = Modality::find($this->modality);
            $this->group = $modalityModel->active_additional_rules ? 'classification' : null;

            if (isset($payload['eventId'])) {
                $this->eventId = $payload['eventId'];
            }

            Log::info('ShowHud::handleHudEvent - Updated from websocket', [
                'modality_id' => $this->modality,
                'current_round' => $this->currentRoundValue,
                'final_round' => $this->finalRound,
                'event_id' => $this->eventId,
            ]);

            $this->dispatch('$refresh');
        } else {
            Log::warning('ShowHud::handleHudEvent - Invalid modality', [
                'payload' => $payload,
            ]);
        }
    }

    /**
     * CORRIGIDO: Determina a rodada atual com prioridade: Buffer > Banco
     */
    private function getCurrentRoundNumber(): int
    {
        if (!$this->modality || !$this->eventId) {
            return 1;
        }

        // 1. PRIORIDADE MÁXIMA: Verifica se existe buffer (rodada em andamento)
        $latestBuffer = RoundBuffer::where('modality_id', $this->modality)
            ->where('event_id', $this->eventId)
            ->where(function ($query) {
                if (is_null($this->group) || $this->group === '') {
                    $query->whereNull('group')->orWhere('group', '');
                } else {
                    $query->where('group', $this->group);
                }
            })
            ->orderBy('number', 'desc')
            ->first();

        if ($latestBuffer) {
            Log::info('ShowHud - Current round from BUFFER', [
                'round_number' => $latestBuffer->number,
            ]);
            return $latestBuffer->number;
        }

        // 2. Busca última rodada finalizada no banco
        $lastRound = Round::where('modality_id', $this->modality)
            ->where('event_id', $this->eventId)
            ->where(function ($query) {
                if (is_null($this->group) || $this->group === '') {
                    $query->whereNull('group')->orWhere('group', '');
                } else {
                    $query->where('group', $this->group);
                }
            })
            ->orderBy('number', 'desc')
            ->first();

        if ($lastRound) {
            Log::info('ShowHud - Current round from DATABASE', [
                'round_number' => $lastRound->number,
            ]);
            return $lastRound->number;
        }

        // 3. Fallback: rodada 1
        Log::info('ShowHud - Current round FALLBACK to 1');
        return 1;
    }

    private function loadActiveOrFinalizedModality(): void
    {
        $activeModality = Modality::with(['events', 'rules'])
            ->where('status_modality', 0)
            ->orderBy('updated_at', 'desc')
            ->first();

        if ($activeModality) {
            $this->modality = $activeModality->id;
            $this->group = $activeModality->active_additional_rules ? 'classification' : null;

            $firstEvent = $activeModality->events()->first();
            if ($firstEvent) {
                $this->eventId = $firstEvent->id;
            }

            // USA O NOVO MÉTODO CORRIGIDO
            $this->currentRoundValue = $this->getCurrentRoundNumber();
            $this->finalRound = $activeModality->round_initial;

            Log::info('ShowHud - Auto-loaded active modality', [
                'modality_id' => $this->modality,
                'modality_name' => $activeModality->name,
                'event_id' => $this->eventId,
                'event_name' => $firstEvent?->name ?? 'N/A',
                'current_round' => $this->currentRoundValue,
                'final_round' => $this->finalRound,
                'group' => $this->group,
            ]);

            return;
        }

        $finalizedModality = Modality::with(['events'])
            ->where('status_modality', 1)
            ->orderBy('updated_at', 'desc')
            ->first();

        if ($finalizedModality) {
            $this->modality = $finalizedModality->id;
            $this->group = $finalizedModality->active_additional_rules ? 'classification' : null;

            $firstEvent = $finalizedModality->events()->first();
            if ($firstEvent) {
                $this->eventId = $firstEvent->id;
            }

            Log::info('ShowHud - Auto-loaded finalized modality', [
                'modality_id' => $this->modality,
                'modality_name' => $finalizedModality->name,
                'event_id' => $this->eventId,
                'event_name' => $firstEvent?->name ?? 'N/A',
            ]);

            return;
        }

        Log::warning('ShowHud - No active or finalized modality found');
    }

    public function getModalityName()
    {
        if (!$this->modality) {
            return [
                'name' => '',
                'event_name' => '',
                'value' => '',
                'rule_participant' => '',
                'rule_life' => '',
            ];
        }

        $modality = Modality::with(['events', 'rules'])
            ->find($this->modality);

        if (!$modality) {
            Log::warning('ShowHud::getModalityName - Modality not found', [
                'modality_id' => $this->modality,
            ]);

            return [
                'name' => '',
                'event_name' => '',
                'value' => '',
                'rule_participant' => '',
                'rule_life' => '',
            ];
        }

        if (!$modality->events || $modality->events->isEmpty()) {
            return [
                'name' => $modality->name ?? '',
                'event_name' => '',
                'value' => $modality->inscription_value ?? '',
                'rule_participant' => $modality->rules->participant_rule ?? '',
                'rule_life' => $modality->rules->rule_life ?? '',
            ];
        }

        return [
            'name' => $modality->name,
            'event_name' => $modality->events[0]->name,
            'value' => $modality->inscription_value,
            'rule_participant' => $modality->rules->participant_rule ?? '',
            'rule_life' => $modality->rules->rule_life ?? '',
        ];
    }

    public function getHudImage()
    {
        if (!$this->modality) {
            return [];
        }

        $modality = Modality::with(['events.hud'])
            ->find($this->modality);

        if (!$modality) {
            Log::warning('ShowHud::getHudImage - Modality not found', [
                'modality_id' => $this->modality,
            ]);
            return [];
        }

        $dataHud = [];

        foreach ($modality->events as $event) {
            foreach ($event->hud as $item) {
                $dataHud[] = $item->image;
            }
        }

        return $dataHud;
    }

    public function show()
    {
        if (!$this->modality) {
            Log::warning('ShowHud::show() - No modality set');

            return [
                'active_rounds' => [],
                'finalized_participants' => [],
            ];
        }

        $modalityModel = Modality::with(['events', 'rules'])
            ->find($this->modality);

        if (!$modalityModel) {
            Log::error('ShowHud::show() - Modality not found', [
                'modality_id' => $this->modality,
            ]);

            return [
                'active_rounds' => [],
                'finalized_participants' => [],
            ];
        }

        if (!$this->eventId) {
            $firstEvent = $modalityModel->events()->first();
            if ($firstEvent) {
                $this->eventId = $firstEvent->id;
            }
        }

        $isModalityFinalized = $modalityModel->status_modality == 1;

        if ($isModalityFinalized) {
            Log::info('ShowHud::show() - Modality is finalized, showing results table');

            return [
                'active_rounds' => [],
                'finalized_participants' => $this->processFinalizedParticipants(),
            ];
        }

        if (!$this->currentRoundValue) {
            Log::warning('ShowHud::show() - Missing currentRoundValue for active modality');

            return [
                'active_rounds' => [],
                'finalized_participants' => [],
            ];
        }

        $this->inscriptions = Inscription::with(['participants'])
            ->where('modality_id', $this->modality)
            ->where('inscription_status', true)
            ->get();

        $dataRounds = [
            'active_rounds' => [],
            'finalized_participants' => [],
        ];

        $currentRound = $this->currentRoundValue;

        // Buffer da rodada ESPECÍFICA
        $buffer = RoundBuffer::where([
            'modality_id' => $this->modality,
            'number' => $currentRound,
        ])
            ->where(function ($query) {
                if (is_null($this->group) || $this->group === '') {
                    $query->whereNull('group')->orWhere('group', '');
                } else {
                    $query->where('group', $this->group);
                }
            })
            ->first();

        $bufferPayload = $buffer?->payload ?? [];

        Log::info('ShowHud::show() - Buffer check', [
            'current_round' => $currentRound,
            'has_buffer' => !is_null($buffer),
            'buffer_payload_count' => count($bufferPayload),
        ]);

        // Rounds do banco da rodada ESPECÍFICA
        $existingRounds = Round::where([
            'modality_id' => $this->modality,
            'number' => $currentRound,
        ])
            ->where(function ($query) {
                if (is_null($this->group) || $this->group === '') {
                    $query->whereNull('group')->orWhere('group', '');
                } else {
                    $query->where('group', $this->group);
                }
            })
            ->get()->keyBy(function ($item) {
                return $item->inscription_id . '|' . $item->participant_id;
            });

        Log::info('ShowHud::show() - Database rounds check', [
            'current_round' => $currentRound,
            'rounds_count' => $existingRounds->count(),
        ]);

        foreach ($this->inscriptions as $inscription) {
            foreach ($inscription->participants as $participant) {
                $key = $inscription->id . '|' . $participant->id;

                $value = null;

                // Prioriza buffer > banco
                if (isset($bufferPayload[$inscription->id][$participant->id])) {
                    $value = $bufferPayload[$inscription->id][$participant->id];
                } elseif ($existingRounds->has($key)) {
                    $value = $existingRounds->get($key)->value;
                }

                $dataRounds['active_rounds'][$currentRound]['participants'][$participant->id] = [
                    'name' => $participant->name,
                    'value' => $value,
                    'round' => $currentRound,
                    'inscription' => $inscription->inscription_number,
                    'group_name' => $inscription->name ?? '',
                    'strength' => $participant->strength ?? 'N/A',
                ];
            }
        }

        return $dataRounds;
    }

    private function processFinalizedParticipants()
    {
        if (!$this->modality || !$this->eventId) {
            return [];
        }

        $finalizedParticipants = Inscription::with(['participants'])
            ->where('modality_id', $this->modality)
            ->where('event_id', $this->eventId)
            ->get();

        if ($finalizedParticipants->isEmpty()) {
            return [];
        }

        $allRounds = Round::where('modality_id', $this->modality)
            ->where('event_id', $this->eventId)
            ->where(function ($query) {
                if (is_null($this->group) || $this->group === '') {
                    $query->whereNull('group')->orWhere('group', '');
                } else {
                    $query->where('group', $this->group);
                }
            })
            ->orderBy('number')
            ->get()
            ->groupBy('participant_id');

        $finalized = [];

        foreach ($finalizedParticipants as $inscription) {
            foreach ($inscription->participants as $participant) {
                $participantRounds = $allRounds->get($participant->id, collect());
                $totalScore = $participantRounds->sum('value');

                $finalized[] = [
                    'name' => $participant->name ?? '',
                    'surname' => $participant->surname ?? '',
                    'inscription' => $inscription->inscription_number,
                    'strength' => $participant->strength ?? 'N/A',
                    'total' => $totalScore,
                ];
            }
        }

        usort($finalized, function ($a, $b) {
            return $b['total'] <=> $a['total'];
        });

        $colocation = 1;
        foreach ($finalized as &$participant) {
            $participant['colocation'] = $colocation;
            $colocation++;
        }

        return $finalized;
    }

    public function refreshRounds()
    {
        if (!$this->modality) {
            $this->loadActiveOrFinalizedModality();
        }

        if (!$this->modality) {
            return;
        }

        $modalityModel = Modality::find($this->modality);

        if ($modalityModel && $modalityModel->status_modality == 0) {
            // Atualiza rodada atual; se mudou, reinicia janela e assinatura
            $newRound = $this->getCurrentRoundNumber();
            if ($this->currentRoundValue !== $newRound) {
                $this->viewportStartIndex = 0;
                $this->lastTriggerSignature = null;
            }
            $this->currentRoundValue = $newRound;
        }

        $this->getModalityName();
        $this->getHudImage();
        $this->show();
    }

    public function render()
    {
        return view('livewire.hud', [
            'dataRounds' => $this->show(),
            'finalRound' => $this->finalRound,
            'currentRoundValue' => $this->currentRoundValue,
            'modalityName' => $this->getModalityName(),
            'dataHud' => $this->getHudImage(),
            'lastTriggerSignature' => $this->lastTriggerSignature,
        ]);
    }

    #[On('advance-viewport')]
    public function advanceViewport($signature = null)
    {
        // Avança a janela visível; o wrap é tratado na Blade
        $this->viewportStartIndex++;
        // Memoriza a última assinatura que disparou avanço
        if ($signature) {
            $this->lastTriggerSignature = $signature;
        }
    }
}
