import { createFileRoute, redirect } from "@tanstack/react-router";
import { useState, useCallback } from "react";
import type { GameSession, GameRequest, AnswerResult } from "@lila/shared";
import { QuestionCard } from "../components/game/QuestionCard";
import { ScoreScreen } from "../components/game/ScoreScreen";
import { GameSetup } from "../components/game/GameSetup";
import RouteError from "../components/RouteError";
import { authClient } from "../lib/auth-client";

type GameStartResponse = { success: true; data: GameSession };
type GameAnswerResponse = { success: true; data: AnswerResult };

const API_URL = (import.meta.env["VITE_API_URL"] as string) || "";

function Play() {
  const [gameSession, setGameSession] = useState<GameSession | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
  const [results, setResults] = useState<AnswerResult[]>([]);
  const [currentResult, setCurrentResult] = useState<AnswerResult | null>(null);

  const startGame = useCallback(async (settings: GameRequest) => {
    setIsLoading(true);

    const response = await fetch(`${API_URL}/api/v1/game/start`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      credentials: "include",
      body: JSON.stringify(settings),
    });

    const data = (await response.json()) as GameStartResponse;
    setGameSession(data.data);
    setCurrentQuestionIndex(0);
    setResults([]);
    setCurrentResult(null);
    setIsLoading(false);
  }, []);

  const resetToSetup = useCallback(() => {
    setGameSession(null);
    setIsLoading(false);
    setCurrentQuestionIndex(0);
    setResults([]);
    setCurrentResult(null);
  }, []);

  const handleAnswer = async (optionId: number) => {
    if (!gameSession || currentResult) return;

    const question = gameSession.questions[currentQuestionIndex];
    if (!question) return;

    const response = await fetch(`${API_URL}/api/v1/game/answer`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      credentials: "include",
      body: JSON.stringify({
        sessionId: gameSession.sessionId,
        questionId: question.questionId,
        selectedOptionId: optionId,
      }),
    });
    const data = (await response.json()) as GameAnswerResponse;
    setCurrentResult(data.data);
  };

  const handleNext = () => {
    if (!currentResult) return;
    setResults((prev) => [...prev, currentResult]);
    setCurrentQuestionIndex((prev) => prev + 1);
    setCurrentResult(null);
  };

  // Phase: setup
  if (!gameSession && !isLoading) {
    return (
      <div className="min-h-screen bg-linear-to-b from-purple-100 to-pink-50 flex items-center justify-center p-6">
        <GameSetup
          onStart={(settings) => {
            void startGame(settings).catch((err) => {
              console.error("Start game error:", err);
            });
          }}
        />
      </div>
    );
  }

  // Phase: loading
  if (isLoading || !gameSession) {
    return (
      <div className="min-h-screen bg-linear-to-b from-purple-100 to-pink-50 flex items-center justify-center">
        <p className="text-purple-400 text-lg font-medium">Loading...</p>
      </div>
    );
  }

  // Phase: finished
  if (currentQuestionIndex >= gameSession.questions.length) {
    return (
      <div className="min-h-screen bg-linear-to-b from-purple-100 to-pink-50 flex items-center justify-center p-6">
        <ScoreScreen results={results} onPlayAgain={resetToSetup} />
      </div>
    );
  }

  // Phase: playing
  const question = gameSession.questions[currentQuestionIndex]!;

  return (
    <div className="min-h-screen bg-linear-to-b from-purple-100 to-pink-50 flex items-center justify-center p-6">
      <QuestionCard
        onAnswer={(optionId) => {
          void handleAnswer(optionId).catch((err) => {
            console.error("Answer error:", err);
          });
        }}
        question={question}
        questionNumber={currentQuestionIndex + 1}
        totalQuestions={gameSession.questions.length}
        currentResult={currentResult}
        onNext={handleNext}
      />
    </div>
  );
}

export const Route = createFileRoute("/play")({
  component: Play,
  errorComponent: RouteError,
  beforeLoad: async () => {
    const { data: session } = await authClient.getSession();
    if (!session) {
      throw redirect({ to: "/", search: { modal: "auth", redirect: "/play" } });
    }
  },
});
