import { useState, useEffect, useRef } from "react";
import { useParams, Link, useSearchParams } from "react-router-dom";
import ReactMarkdown from "react-markdown";
import { useAuth } from "../contexts/AuthContext";
import {
  getStory,
  getSessionsList,
  getSession,
  createSession,
  saveSession as apiSaveSession,
  deleteSession as apiDeleteSession,
  getPlayerCharacter,
  type SessionListItem,
} from "../services/api";
import {
  generateStoryResponseStream,
  buildSystemPrompt,
  sendMessage,
  generateStorySummary,
  extractKeyEvents,
} from "../services/deepseek";
import type {
  Story,
  GameSession,
  ChatMessage,
  PlayerCharacter,
} from "../types";
import "./GamePage.css";

function generateId(): string {
  return Math.random().toString(36).substring(2) + Date.now().toString(36);
}

// Примерный подсчёт токенов (1 токен ≈ 3 символа для русского)
function estimateTokens(messages: ChatMessage[]): number {
  if (!messages || messages.length === 0) return 0;
  const totalChars = messages.reduce((sum, msg) => sum + msg.content.length, 0);
  return Math.round(totalChars / 3);
}

function formatTokens(tokens: number): string {
  if (tokens >= 1000000) return `${(tokens / 1000000).toFixed(1)}M`;
  if (tokens >= 1000) return `${(tokens / 1000).toFixed(1)}K`;
  return tokens.toString();
}

export default function GamePage() {
  const { id } = useParams<{ id: string }>();
  const [searchParams] = useSearchParams();
  const { isAuthenticated } = useAuth();
  const [story, setStory] = useState<Story | null>(null);
  const [sessionsList, setSessionsList] = useState<SessionListItem[]>([]);
  const [currentSessionId, setCurrentSessionId] = useState<string | null>(null);
  const [session, setSession] = useState<GameSession | null>(null);
  const [playerCharacter, setPlayerCharacter] =
    useState<PlayerCharacter | null>(null);
  const [input, setInput] = useState("");
  const [isLoading, setIsLoading] = useState(false);
  const [isInitialLoading, setIsInitialLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [streamingContent, setStreamingContent] = useState("");
  const [showSessionMenu, setShowSessionMenu] = useState(false);
  const abortControllerRef = useRef<AbortController | null>(null);
  const messagesEndRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLTextAreaElement>(null);

  useEffect(() => {
    const loadGame = async () => {
      if (!id || !isAuthenticated) {
        setIsInitialLoading(false);
        return;
      }

      const foundStory = await getStory(id);
      if (foundStory) {
        const normalizedStory = {
          ...foundStory,
          id: (foundStory as any)._id || foundStory.id,
        };
        setStory(normalizedStory);

        // Загружаем список сессий
        const sessions = await getSessionsList(id);
        console.log("[GamePage] Sessions list:", sessions);
        setSessionsList(sessions);

        const characterId = searchParams.get("character");

        // Загружаем персонажа
        let character: PlayerCharacter | null = null;
        if (characterId) {
          character = await getPlayerCharacter(characterId);
          setPlayerCharacter(character);
        }

        // Если есть сессии, загружаем последнюю (или создаём новую)
        if (sessions.length > 0) {
          const latestSession = sessions[0];
          console.log("[GamePage] Loading latest session:", latestSession);
          setCurrentSessionId(latestSession.id);
          const sessionData = await getSession(id, latestSession.id);
          console.log("[GamePage] Session data loaded:", sessionData);
          if (sessionData) {
            setSession(sessionData);
            // Загружаем персонажа из сессии если не выбран
            if (!character && sessionData.playerId) {
              character = await getPlayerCharacter(sessionData.playerId);
              setPlayerCharacter(character);
            }
          }
        } else if (characterId) {
          // Нет сессий и выбран персонаж — создаём новую
          const newSession = await createSession(id, undefined, characterId);
          if (newSession) {
            setSessionsList([newSession]);
            setCurrentSessionId(newSession.id);
            const sessionData = await getSession(id, newSession.id);
            if (sessionData) {
              setSession(sessionData);
              if (character) {
                startStory(
                  normalizedStory,
                  sessionData,
                  character,
                  newSession.id,
                );
              }
            }
          }
        }
      }
      setIsInitialLoading(false);
    };

    loadGame();
  }, [id, isAuthenticated, searchParams]);

  // Обновляем историю при возврате на страницу (после редактирования)
  useEffect(() => {
    const handleFocus = async () => {
      if (!id || !isAuthenticated || isInitialLoading) return;

      const updatedStory = await getStory(id);
      if (updatedStory) {
        const normalizedStory = {
          ...updatedStory,
          id: (updatedStory as any)._id || updatedStory.id,
        };
        setStory(normalizedStory);
        console.log("[GamePage] История обновлена после возврата на страницу");
      }
    };

    window.addEventListener("focus", handleFocus);
    return () => window.removeEventListener("focus", handleFocus);
  }, [id, isAuthenticated, isInitialLoading]);

  useEffect(() => {
    scrollToBottom();
  }, [session?.messages]);

  const scrollToBottom = () => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
  };

  const startStory = async (
    storyData: Story,
    sessionData: GameSession,
    character: PlayerCharacter,
    sessionId: string,
  ) => {
    // Если есть заготовленное первое сообщение, используем его
    if (storyData.firstMessage && storyData.firstMessage.trim()) {
      // Заменяем {user} на имя персонажа
      const firstMessageContent = storyData.firstMessage.replace(
        /\{user\}/gi,
        character.name,
      );
      const assistantMessage: ChatMessage = {
        id: generateId(),
        role: "assistant",
        content: firstMessageContent,
        timestamp: new Date(),
      };

      const updatedSession: GameSession = {
        ...sessionData,
        messages: [assistantMessage],
      };

      await apiSaveSession(storyData.id, sessionId, updatedSession);
      setSession(updatedSession);
      return;
    }

    // Иначе генерируем через ИИ
    setIsLoading(true);
    setError(null);

    try {
      const systemPrompt = buildSystemPrompt(storyData, character);
      const response = await sendMessage([
        { role: "system", content: systemPrompt },
        { role: "user", content: "Начни историю." },
      ]);

      const assistantMessage: ChatMessage = {
        id: generateId(),
        role: "assistant",
        content: response,
        timestamp: new Date(),
      };

      const updatedSession: GameSession = {
        ...sessionData,
        messages: [assistantMessage],
      };

      await apiSaveSession(storyData.id, sessionId, updatedSession);
      setSession(updatedSession);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Произошла ошибка");
    } finally {
      setIsLoading(false);
    }
  };

  const handleSend = async () => {
    if (!input.trim() || !story || !session || !currentSessionId || isLoading)
      return;

    const userMessage: ChatMessage = {
      id: generateId(),
      role: "user",
      content: input.trim(),
      timestamp: new Date(),
    };

    const updatedMessages = [...session.messages, userMessage];
    const tempSession = { ...session, messages: updatedMessages };
    setSession(tempSession);
    setInput("");
    // Reset textarea height
    if (inputRef.current) {
      inputRef.current.style.height = "auto";
    }
    setIsLoading(true);
    setError(null);
    setStreamingContent("");

    // Создаём AbortController для возможности отмены
    abortControllerRef.current = new AbortController();

    try {
      // Streaming ответ от AI
      const response = await generateStoryResponseStream(
        story,
        session.messages,
        input.trim(),
        (chunk) => {
          setStreamingContent((prev) => prev + chunk);
        },
        playerCharacter || undefined,
        session,
        abortControllerRef.current.signal,
      );

      const assistantMessage: ChatMessage = {
        id: generateId(),
        role: "assistant",
        content: response,
        timestamp: new Date(),
      };

      const allMessages = [...updatedMessages, assistantMessage];

      // Обновляем ключевые события
      const newKeyEvents = await extractKeyEvents(
        response,
        session.keyEvents || [],
      );

      // Генерируем сводку каждые 20 сообщений
      let newSummary = session.storySummary;
      if (allMessages.length % 20 === 0 && allMessages.length > 0) {
        console.log("[GamePage] Generating story summary...");
        newSummary = await generateStorySummary(
          story,
          allMessages,
          session.storySummary,
        );
      }

      const finalSession: GameSession = {
        ...session,
        messages: allMessages,
        keyEvents: newKeyEvents,
        storySummary: newSummary,
      };

      const saved = await apiSaveSession(
        story.id,
        currentSessionId,
        finalSession,
      );
      console.log(
        "[GamePage] Session saved:",
        saved,
        "Messages:",
        allMessages.length,
      );
      setSession(finalSession);
    } catch (err) {
      if (err instanceof Error && err.name === "AbortError") {
        // Пользователь отменил — сохраняем то что получили
        if (streamingContent.trim()) {
          const partialMessage: ChatMessage = {
            id: generateId(),
            role: "assistant",
            content: streamingContent,
            timestamp: new Date(),
          };
          const partialSession: GameSession = {
            ...session,
            messages: [...updatedMessages, partialMessage],
          };
          await apiSaveSession(story.id, currentSessionId, partialSession);
          setSession(partialSession);
        }
      } else {
        setError(err instanceof Error ? err.message : "Произошла ошибка");
        setSession(session);
        setInput(userMessage.content);
      }
    } finally {
      setIsLoading(false);
      setStreamingContent("");
      abortControllerRef.current = null;
      inputRef.current?.focus();
    }
  };

  const handleStop = () => {
    if (abortControllerRef.current) {
      abortControllerRef.current.abort();
    }
  };

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      handleSend();
    }
  };

  // Функции управления сессиями
  const handleCreateNewSession = async () => {
    if (!story || !id) return;
    setShowSessionMenu(false);

    // Используем персонажа из текущей сессии или выбранного
    const characterId = playerCharacter?.id || session?.playerId;
    if (!characterId) {
      alert("Не выбран персонаж для игры");
      return;
    }

    const name = `Сессия ${sessionsList.length + 1}`;
    const newSession = await createSession(id, name, characterId);
    if (newSession) {
      setSessionsList([newSession, ...sessionsList]);
      setCurrentSessionId(newSession.id);
      const sessionData = await getSession(id, newSession.id);
      if (sessionData) {
        setSession(sessionData);
        // Загружаем персонажа если нет
        let character = playerCharacter;
        if (!character && characterId) {
          character = await getPlayerCharacter(characterId);
          setPlayerCharacter(character);
        }
        if (character) {
          startStory(story, sessionData, character, newSession.id);
        }
      }
    }
  };

  const handleSwitchSession = async (sessionId: string) => {
    console.log("[GamePage] Switching to session:", sessionId, "current:", currentSessionId);
    if (!id || sessionId === currentSessionId) {
      setShowSessionMenu(false);
      return;
    }

    setShowSessionMenu(false);
    setIsInitialLoading(true);

    const sessionData = await getSession(id, sessionId);
    console.log("[GamePage] Loaded session data:", sessionData);
    if (sessionData) {
      setCurrentSessionId(sessionId);
      setSession(sessionData);
      // Загружаем персонажа сессии
      if (sessionData.playerId) {
        const character = await getPlayerCharacter(sessionData.playerId);
        setPlayerCharacter(character);
      }
    }
    setIsInitialLoading(false);
  };

  const handleDeleteSession = async (sessionId: string) => {
    if (!id || sessionsList.length <= 1) {
      alert("Нельзя удалить единственную сессию");
      return;
    }

    if (!confirm("Удалить эту сессию? Это действие нельзя отменить.")) {
      return;
    }

    const success = await apiDeleteSession(id, sessionId);
    if (success) {
      const updatedList = sessionsList.filter((s) => s.id !== sessionId);
      setSessionsList(updatedList);

      // Если удалили текущую сессию — переключаемся на другую
      if (sessionId === currentSessionId && updatedList.length > 0) {
        await handleSwitchSession(updatedList[0].id);
      }
    }
    setShowSessionMenu(false);
  };

  const currentSessionName =
    sessionsList.find((s) => s.id === currentSessionId)?.name || "Сессия";

  if (isInitialLoading) {
    return (
      <div className="game-page">
        <div className="game-loading">
          <p>Загрузка игры...</p>
        </div>
      </div>
    );
  }

  if (!story) {
    return (
      <div className="game-page">
        <div className="game-error">
          <h2>История не найдена</h2>
          <Link to="/" className="back-link">
            ← Вернуться к списку
          </Link>
        </div>
      </div>
    );
  }

  return (
    <div className="game-page">
      <header className="game-header">
        <Link to={`/story/${story.id}`} className="back-btn">
          ←
        </Link>
        <div className="header-info">
          <h1>{story.title}</h1>
          <div className="header-session">
            <button
              className="session-selector"
              onClick={() => setShowSessionMenu(!showSessionMenu)}
            >
              📖 {currentSessionName} ▾
            </button>
            {showSessionMenu && (
              <div className="session-menu">
                <div className="session-menu-header">
                  <span>Сессии</span>
                  <button
                    className="new-session-btn"
                    onClick={handleCreateNewSession}
                    title="Новая сессия"
                  >
                    ➕
                  </button>
                </div>
                <div className="session-list">
                  {sessionsList.map((s) => (
                    <div
                      key={s.id}
                      className={`session-item ${s.id === currentSessionId ? "active" : ""}`}
                    >
                      <button
                        className="session-name"
                        onClick={() => handleSwitchSession(s.id)}
                      >
                        {s.name}
                        <span className="session-messages">
                          {s.messagesCount} сообщ.
                        </span>
                      </button>
                      {sessionsList.length > 1 && (
                        <button
                          className="delete-session-btn"
                          onClick={(e) => {
                            e.stopPropagation();
                            handleDeleteSession(s.id);
                          }}
                          title="Удалить сессию"
                        >
                          🗑️
                        </button>
                      )}
                    </div>
                  ))}
                </div>
              </div>
            )}
          </div>
        </div>
        <div className="header-stats">
          <span className="stat-badge tokens">
            🎟️ {formatTokens(estimateTokens(session?.messages || []))}
          </span>
        </div>
      </header>

      <div className="game-content">
        <div className="messages-container">
          {session?.messages.map((message) => (
            <div key={message.id} className={`message ${message.role}`}>
              <div className="message-content">
                <ReactMarkdown>{message.content}</ReactMarkdown>
              </div>
              <span className="message-time">
                {new Date(message.timestamp).toLocaleTimeString("ru-RU", {
                  hour: "2-digit",
                  minute: "2-digit",
                })}
              </span>
            </div>
          ))}

          {isLoading && streamingContent && (
            <div className="message assistant streaming">
              <div className="message-content">
                <ReactMarkdown>{streamingContent}</ReactMarkdown>
              </div>
            </div>
          )}

          {isLoading && !streamingContent && (
            <div className="message assistant loading">
              <div className="typing-indicator">
                <span></span>
                <span></span>
                <span></span>
              </div>
            </div>
          )}

          {error && (
            <div className="error-message">
              <span>⚠️ {error}</span>
              <button onClick={() => setError(null)}>✕</button>
            </div>
          )}

          <div ref={messagesEndRef} />
        </div>

        {/* RPG кнопки скрыты — раскомментировать при необходимости
        <div className="quick-actions">
          <button onClick={() => handleQuickAction("Осмотреться вокруг")}>
            👀 Осмотреться
          </button>
          <button onClick={() => handleQuickAction("Проверить инвентарь")}>
            🎒 Инвентарь
          </button>
          <button onClick={() => handleQuickAction("Поговорить с кем-нибудь")}>
            💬 Говорить
          </button>
          <button onClick={() => handleQuickAction("Идти вперёд")}>
            🚶 Идти
          </button>
        </div>
        */}

        <form className="input-container" onSubmit={(e) => { e.preventDefault(); handleSend(); }}>
          <textarea
            ref={inputRef}
            value={input}
            onChange={(e) => {
              setInput(e.target.value);
              // Auto-resize
              e.target.style.height = "auto";
              e.target.style.height = Math.min(e.target.scrollHeight, 150) + "px";
            }}
            onKeyDown={handleKeyDown}
            placeholder="Что ты хочешь сделать?..."
            disabled={isLoading}
            rows={1}
            name="chat-input"
            autoComplete="off"
            autoCorrect="off"
            autoCapitalize="off"
            spellCheck={false}
            enterKeyHint="send"
            data-form-type="other"
            data-lpignore="true"
            data-gramm="false"
          />
          {isLoading ? (
            <button type="button" onClick={handleStop} className="send-btn stop-btn">
              ⏹
            </button>
          ) : (
            <button
              type="submit"
              disabled={!input.trim()}
              className="send-btn"
            >
              ➤
            </button>
          )}
        </form>
      </div>
    </div>
  );
}
