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,
  getSession,
  saveSession as apiSaveSession,
  getPlayerCharacter,
} from "../services/api";
import {
  generateStoryResponse,
  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();
}

// Пытаемся определить локацию из последних сообщений
function detectLocation(messages: ChatMessage[]): string {
  if (!messages || messages.length === 0) return "Неизвестно";

  // Берём последние 3 сообщения ассистента
  const recentAssistant = messages
    .filter((m) => m.role === "assistant")
    .slice(-3)
    .map((m) => m.content)
    .join(" ");

  // Паттерны для определения локации
  const locationPatterns = [
    /(?:находи(?:тесь|шься)|оказыва(?:етесь|ешься)|стои(?:те|шь))\s+(?:в|на|у)\s+([^.,!?]+)/i,
    /(?:вошл[аи]?|входи(?:те|шь)|попада(?:ете|ешь))\s+(?:в|на)\s+([^.,!?]+)/i,
    /(?:прибыл[аи]?|приход(?:ите|ишь)|добрал(?:ись|ась|ся))\s+(?:в|на|до)\s+([^.,!?]+)/i,
    /(?:комнат[аеуы]|зал[аеуы]?|пещер[аеуы]|лес[ау|замок|двор(?:ец)?|тавер[нуыа]|город[ауе]?|деревн[яюией]|тронн[ыйая]|подземель[яеи])\s*([^.,!?]*)/i,
  ];

  for (const pattern of locationPatterns) {
    const match = recentAssistant.match(pattern);
    if (match && match[1]) {
      // Чистим и обрезаем результат
      let location = match[1].trim();
      if (location.length > 25) location = location.substring(0, 25) + "...";
      return location;
    }
  }

  // Простой поиск ключевых слов
  const simpleLocations: [RegExp, string][] = [
    [/тронн(?:ый|ого|ом)\s*зал/i, "Тронный зал"],
    [/тавер[нуыа]/i, "Таверна"],
    [/замок|замк[ауе]/i, "Замок"],
    [/лес[ау]?/i, "Лес"],
    [/пещер[аеуы]/i, "Пещера"],
    [/город[ауе]?/i, "Город"],
    [/деревн[яюией]/i, "Деревня"],
    [/подземель[яеи]/i, "Подземелье"],
    [/двор(?:ец|ц[ауе])/i, "Дворец"],
    [/рын(?:ок|к[ауе])/i, "Рынок"],
    [/храм[ауе]?/i, "Храм"],
    [/библиотек/i, "Библиотека"],
    [/казарм/i, "Казармы"],
  ];

  for (const [pattern, name] of simpleLocations) {
    if (pattern.test(recentAssistant)) {
      return name;
    }
  }

  return "Неизвестно";
}

export default function GamePage() {
  const { id } = useParams<{ id: string }>();
  const [searchParams] = useSearchParams();
  const { isAuthenticated } = useAuth();
  const [story, setStory] = useState<Story | 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 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);

        let existingSession = await getSession(id);
        console.log(
          "[GamePage] Loaded session:",
          existingSession?.messages?.length || 0,
          "messages",
        );
        const characterId = searchParams.get("character");

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

        if (!existingSession) {
          console.log("[GamePage] No existing session, creating new");
          existingSession = {
            storyId: id,
            playerId: characterId || undefined,
            messages: [],
            currentState: {
              location: "Неизвестно",
              health: 100,
              inventory: [],
              questProgress: {},
            },
          };
        } else if (characterId && existingSession.playerId !== characterId) {
          // Новый персонаж — новая сессия
          console.log("[GamePage] New character selected, resetting session");
          existingSession = {
            storyId: id,
            playerId: characterId,
            messages: [],
            currentState: {
              location: "Неизвестно",
              health: 100,
              inventory: [],
              questProgress: {},
            },
          };
        } else {
          console.log(
            "[GamePage] Using existing session with",
            existingSession.messages.length,
            "messages",
          );
        }

        setSession(existingSession);

        // Начинаем историю если это новая сессия
        if (existingSession.messages.length === 0 && character) {
          startStory(normalizedStory, existingSession, character);
        }
      }
      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,
  ) => {
    // Если есть заготовленное первое сообщение, используем его
    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, 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, updatedSession);
      setSession(updatedSession);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Произошла ошибка");
    } finally {
      setIsLoading(false);
    }
  };

  const handleSend = async () => {
    if (!input.trim() || !story || !session || 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("");
    setIsLoading(true);
    setError(null);

    try {
      // Передаём session для оптимизированного контекста
      const response = await generateStoryResponse(
        story,
        session.messages,
        input.trim(),
        playerCharacter || undefined,
        session,
      );

      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, finalSession);
      console.log(
        "[GamePage] Session saved:",
        saved,
        "Messages:",
        allMessages.length,
      );
      setSession(finalSession);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Произошла ошибка");
      // Откатываем сообщение пользователя при ошибке
      setSession(session);
      setInput(userMessage.content);
    } finally {
      setIsLoading(false);
      inputRef.current?.focus();
    }
  };

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

  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>
          <span className="header-protagonist">
            👤 {playerCharacter?.name || "Герой"}
          </span>
        </div>
        <div className="header-stats">
          <span className="stat-badge tokens">
            🎟️ {formatTokens(estimateTokens(session?.messages || []))}
          </span>
          <span className="stat-badge location">
            📍 {detectLocation(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 && (
            <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>
        */}

        <div className="input-container">
          <textarea
            ref={inputRef}
            value={input}
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={handleKeyDown}
            placeholder="Что ты хочешь сделать?..."
            disabled={isLoading}
            rows={2}
          />
          <button
            onClick={handleSend}
            disabled={!input.trim() || isLoading}
            className="send-btn"
          >
            {isLoading ? "⏳" : "➤"}
          </button>
        </div>
      </div>
    </div>
  );
}
