<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed, nextTick } from 'vue';
import { useRoute } from 'vue-router';
import axios from 'axios';
import type { Lobby, Player } from '../models/public';
import type { GameState } from '../models/GameState';
import router from '../router/router';

const route = useRoute();
const lobbyCode = ref<string | string[]>(route.params.code);
const backendUrl = import.meta.env.VITE_BACKEND_URL;

// Event source for real-time updates
const eventSource = ref<EventSource | null>(null);

// Game state variables
const question = ref<string | null>(null);
const players = ref<Player[]>([]);
const currentQuestionIndex = ref<number>(0);
const timeLeft = ref<number>(15);
const totalQuestions = ref<number>(10);
const timerInterval = ref<number | undefined>(undefined);
const picture = ref<string>();
const isCorrect = ref<boolean>(false);
const questionFinished = ref<boolean>(false);
const correctAnswer = ref<string>('');
const isLobbyCreator = ref<boolean>(false);
const timeoutBetweenQuestions = 3000;

// Answer elements
const answerInput = ref<HTMLInputElement | null>(null);
const typedAnswer = ref<string>('');

// Safe localStorage access function
function getFromLocalStorage(key: string): string | null {
  if (typeof window !== 'undefined' && window.localStorage) {
    return localStorage.getItem(key);
  }
  return null;
}

// Fetch scoreboard
async function fetchScoreboard() {
  try {
    const response = await axios.get(`${backendUrl}/game/${lobbyCode.value}/players`);

    if (!response.data || !Array.isArray(response.data)) {
      return;
    }
 
    const processedPlayers = response.data.map((player: any) => ({
      ...player,
      id: player.id.toString(),
      score: player.score || 0,
    }));

    players.value = processedPlayers.sort((a: Player, b: Player) => b.score - a.score);
  } catch (error) {
    console.error('Error fetching scoreboard:', error);
  }
}

// Submit answer from player.
async function submitAnswer(): Promise<void> {
  const currentUserId = getFromLocalStorage('playerId');
  await axios.post(`${backendUrl}/game/${lobbyCode.value}/answer`, {
    answer: typedAnswer.value,
    userId: currentUserId,
    currentTimer: timeLeft.value,
  });
  typedAnswer.value = '';
}

// starts timer and invokes onComplete function when timer elapsed.
function startTimer(onComplete: () => Promise<void>) {
  clearInterval(timerInterval.value);
  
  // Send initial timer value
  syncTimerWithBackend();
  
  timerInterval.value = setInterval(async () => {
    if (timeLeft.value > 0) {
      timeLeft.value--;
      
      // Sync timer every 3 seconds if you're the lobby creator
      if (isLobbyCreator.value && timeLeft.value % 1 === 0) {
        syncTimerWithBackend();
      }
    } else {
      clearInterval(timerInterval.value);
      await onComplete();
    }
  }, 1000);
}

// Progress percentage
const progressPercentage = computed(() => {
  return ((currentQuestionIndex.value -1) / totalQuestions.value) * 100;
});

// Setting up event Source and processing events.
async function setupEventSource(): Promise<void> {
  eventSource.value = new EventSource(`${backendUrl}/game/${lobbyCode.value}/events`);
  eventSource.value.onmessage = async (event) => {
    const data = JSON.parse(event.data);
    const currentUserId = getFromLocalStorage('playerId');

    console.log("CURRENT USER ID:", currentUserId);

    switch (data.type) {
      case 'next_question':
        await fetchScoreboard();
        console.log('STATE', data);
        questionFinished.value = false;
        correctAnswer.value = '';
        isCorrect.value = false;
        updateGameState(data.state);
        break;

      case 'question_correct':
        console.log('QUESTION WAS ANSWERED CORRECT');
        console.log(data.state);
        isCorrect.value = data.state.correctUserId === currentUserId;
        console.log('isCorrect.value', isCorrect.value);

        questionFinished.value = true;
        correctAnswer.value = data.state.correctAnswer;
        clearInterval(timerInterval.value);

        if (isLobbyCreator.value) {
          await new Promise((resolve) => setTimeout(resolve, timeoutBetweenQuestions));
          await axios.post(`${backendUrl}/game/${lobbyCode.value}/continue`);
        }
        break;

      case 'question_timeout':
        console.log('QUESTION WAS Timeouted');
        questionFinished.value = true;
        correctAnswer.value = data.state.correctAnswer;
        clearInterval(timerInterval.value);
        console.log('ISLOBBYCREATOR', isLobbyCreator.value);
        if (isLobbyCreator.value) {
          await new Promise((resolve) => setTimeout(resolve, timeoutBetweenQuestions));
          await axios.post(`${backendUrl}/game/${lobbyCode.value}/continue`);
        }
        break;

      case 'game_finished':
        console.log('GAME IS FINISHED:::::');

        if (eventSource.value) {
          eventSource.value.close();
        }
        clearInterval(timerInterval.value);

        router.push(`scoreboard`);
        break;

        case 'timer_updated':
          console.log('Received timer update:', data.time);
  
          // Only update if you're not the lobby creator (since creator controls the timer)
          if (!isLobbyCreator.value) {
            timeLeft.value = data.time;
            console.log('Local timer updated to:', timeLeft.value);
          }
        break;

      default:
        console.log('unhandeld state');
        console.log(data);
        break;
    }
  };
}

// Invoked on timeout, notifies the backend about the question timeout.
async function timeout() {
  await axios.post(`${backendUrl}/game/${lobbyCode.value}/timeout`);
}

// updates the current Gamestate to the new Gamestate.
function updateGameState(state: GameState) {
  question.value = state.currentQuestion.question;
  timeLeft.value = state.timer;
  picture.value = state.currentQuestion.picture ?? '';
  totalQuestions.value = state.totalQuestions;
  currentQuestionIndex.value = state.currentQuestionIndex;
  typedAnswer.value = '';

  if (answerInput.value) {
    console.log('Focusing on answer input');
    //answerInput.value.focus();
    nextTick(() => {
    setTimeout(() => {
      answerInput.value?.focus();
    }, 100);
  });
  }

  startTimer(timeout);
}

async function syncTimerWithBackend(): Promise<void> {
  try {
    if (isLobbyCreator.value) {
      await axios.post(
        `${backendUrl}/lobbies/${lobbyCode.value}/timer`, 
        {
          time: timeLeft.value
        },
        {
          timeout: 3000 // 3 seconds timeout
        }
      );
      console.log('Timer synced with backend:', timeLeft.value);
    }
  } catch (error: any) {
    if (error.code === 'ECONNABORTED' || (error.message && error.message.includes('timeout'))) {
      console.error('Timer sync request timed out after 3 seconds, reloading page...');
      window.location.reload();
    } else {
      console.error('Error syncing timer:', error);
    }
  }
}

// Fetches the current Gamestate from the backend.
async function fetchGameState(): Promise<void> {
  try {
    const response = await axios.get(`${backendUrl}/lobbies/${lobbyCode.value}/lobby`);
    const currentState = (response.data as Lobby).state as any;

    const currentUserId = getFromLocalStorage('playerId');
    isLobbyCreator.value = Number(response.data.creator_id) === Number(currentUserId);

    if (currentState.state === 'question') {
      updateGameState(currentState);
      return;
    }

    if (isLobbyCreator.value) {
      console.log(
        'Current user is the lobby creator. Waiting 3 seconds before sending continue request...'
      );

      await new Promise((resolve) => setTimeout(resolve, 3000));
      await axios.post(`${backendUrl}/game/${lobbyCode.value}/continue`);
    }
  } catch (error) {
    console.error('Error fetching game state:', error);
  }
}

onMounted(async () => {
  try {
    await fetchScoreboard();

    setupEventSource();

    await fetchGameState();
  } catch (error) {
    console.error('Error during game initialization:', error);
  }
});

onUnmounted(() => {
  if (eventSource.value) {
    eventSource.value.close();
  }
  clearInterval(timerInterval.value);
});
</script>

<template>
  <div
    class="game-container bg-gradient-to-br from-gray-900 via-gray-900 to-gray-900 min-h-screen text-white px-4 py-4 flex flex-col items-center"
  >
    <div
      class="game-header w-full max-w-7xl mx-auto bg-gray-800 rounded-lg shadow-lg p-2 md:p-4 mb-4 flex flex-col md:flex-row items-center justify-between md:space-y-0"
    >
      <h1 class="text-xl md:text-2xl font-bold text-center md:text-left">
        SmolBrainDuel - Lobby: {{ lobbyCode }}
      </h1>
      <div class="w-full md:w-1/2 bg-gray-700 h-2 rounded-full overflow-hidden mt-2">
        <div
          class="bg-blue-300 h-full transition-all duration-300"
          :style="{ width: `${progressPercentage}%` }"
        />
      </div>
      <div class="text-lg text-center md:text-right mt-2">
        Question {{ currentQuestionIndex }} of {{ totalQuestions }}
      </div>
    </div>

    <div class="game-content w-full max-w-7xl grid grid-cols-10 gap-8">
      <div class="question-section col-span-7 bg-gray-800 rounded-lg shadow-lg p-4 md:p-6">
        <div>
          <h2
            v-if="question"
            class="text-xl md:text-2xl font-semibold text-center mb-4 flex items-center justify-center space-x-4"
          >
            <span>{{ question }}</span>
            <div
              class="timer text-xl md:text-2xl font-semibold rounded-full text-center"
              :class="{ 'text-red-500': timeLeft < 5 }"
              style="width: 60px"
            >
              {{ timeLeft }}s
            </div>
          </h2>

          <div
            v-if="question"
            class="image-container w-full h-128 md:h-100 mb-2 overflow-hidden rounded-lg flex justify-center items-center bg-gray-900"
          >
            <img
              :src="`${backendUrl}/${picture}`"
              alt="Image"
              class="max-h-full max-w-full object-contain"
            >
          </div>

          <div
            v-else
            class="loading-indicator text-center text-gray-400 text-xl md:text-2xl font-semibold w-full h-48"
          >
            Starting game...
          </div>

          <input
            ref="answerInput"
            v-model="typedAnswer"
            :disabled="questionFinished"
            class="word-answer-input w-full p-3 bg-gray-700 border border-gray-600 rounded-md text-white placeholder-gray-400 mt-2"
            placeholder="Type your answer here"
            maxlength="20"
            @keyup.enter="!questionFinished && typedAnswer && submitAnswer()"
          >

          <div 
            v-if="questionFinished"
            class="answer-feedback mt-6 mb-4 transition-all duration-500 animate-fade-in"
          >
            <div
              v-if="isCorrect"
              class="correct-feedback bg-green-900/40 border border-green-500/50 rounded-lg p-4 shadow-lg overflow-hidden relative"
            >
              <div class="absolute -top-10 -right-10 w-40 h-40 bg-green-400/20 rounded-full blur-2xl" />
              <div class="flex items-center justify-center">
                <div class="bg-green-500/30 rounded-full p-3 mr-4">
                  <svg
                    xmlns="http://www.w3.org/2000/svg"
                    class="h-8 w-8 text-green-400"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                  >
                    <path
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      stroke-width="2"
                      d="M5 13l4 4L19 7"
                    />
                  </svg>
                </div>
                <div class="text-left">
                  <h3 class="text-green-400 font-bold text-xl mb-1">
                    Correct!
                  </h3>
                  <p class="text-green-300">
                    The answer was: <span class="font-bold bg-green-800/50 px-2 py-0.5 rounded">{{ correctAnswer }}</span>
                  </p>
                </div>
              </div>
            </div>
  
            <div
              v-else
              class="incorrect-feedback bg-red-900/40 border border-red-500/50 rounded-lg p-4 shadow-lg overflow-hidden relative"
            >
              <div class="absolute -top-10 -right-10 w-40 h-40 bg-red-500/20 rounded-full blur-2xl" />
              <div class="flex items-center justify-center">
                <div class="bg-red-500/30 rounded-full p-3 mr-4">
                  <svg
                    xmlns="http://www.w3.org/2000/svg"
                    class="h-8 w-8 text-red-400"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                  >
                    <path
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      stroke-width="2"
                      d="M6 18L18 6M6 6l12 12"
                    />
                  </svg>
                </div>
                <div class="text-left">
                  <h3 class="text-red-400 font-bold text-xl mb-1">
                    Incorrect
                  </h3>
                  <p class="text-red-300">
                    The correct answer is: <span class="font-bold bg-red-800/50 px-2 py-0.5 rounded">{{ correctAnswer }}</span>
                  </p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="scoreboard-section col-span-3 bg-gray-800 rounded-lg shadow-lg p-4 md:p-6">
        <h2 class="text-xl md:text-2xl font-semibold text-center mb-4">
          Scoreboard
        </h2>
        <div
          v-if="players.length === 0"
          class="empty-scoreboard text-center text-gray-400"
        >
          <p>No players found. Please wait...</p>
        </div>
        <div
          v-else
          class="scoreboard space-y-3"
        >
          <transition-group
            name="leaderboard"
            tag="div"
            class="leaderboard-container"
          >
            <div
              v-for="(player, index) in players"
              :key="player.id"
              class="player-score flex items-center justify-between p-3 mb-2 rounded-lg transition-all duration-300"
              :class="{
                'from-yellow-600/50 to-yellow-500/30 bg-gradient-to-r border-l-4 border-yellow-400': index === 0,
                'from-gray-500/50 to-gray-400/30 bg-gradient-to-r border-l-4 border-gray-400': index === 1,
                'from-amber-800/50 to-amber-700/30 bg-gradient-to-r border-l-4 border-amber-700': index === 2,
                'from-gray-700/50 to-gray-600/30 bg-gradient-to-r border-l-4 border-gray-600': index >= 3,
              }"
            >
              <!-- ...existing content... -->
              <div class="flex items-center gap-3">
                <div class="rank flex items-center justify-center w-8 h-8 rounded-full bg-gray-900/60 text-lg font-bold">
                  {{ index === 0 ? '🥇' : index === 1 ? '🥈' : index === 2 ? '🥉' : index + 1 }}
                </div>
                <div class="player-name text-bold text-base md:text-lg flex items-center">
                  <span class="truncate max-w-[120px]">{{ player.name }}</span>
                  <span
                    v-if="player.id == getFromLocalStorage('playerId')"
                    class="ml-2 text-xs text-blue-300"
                  >(You)</span>
                </div>
              </div>
              <div class="player-points relative bg-gray-900/60 rounded-full px-4 py-1 text-lg font-bold">
                <span :class="{'text-yellow-300': index === 0, 'text-gray-300': index === 1, 'text-amber-600': index === 2}">
                  {{ player.score || 0 }}
                </span>
                <span class="text-sm text-gray-400 ml-0.5">pts</span>
              </div>
            </div>
          </transition-group>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
/* Animation for leaderboard position changes */
.leaderboard-move {
  transition: transform 0.6s ease;
}

.leaderboard-enter-active,
.leaderboard-leave-active {
  transition: all 0.6s ease;
}

.leaderboard-enter-from,
.leaderboard-leave-to {
  opacity: 0;
  transform: translateY(30px);
}

.leaderboard-leave-active {
  position: absolute;
}
</style>