import React, { useState, useEffect, useRef } from "react";
import Sidebar from "./Sidebar";
import ChatPanel from "./ChatPanel";
import { Room, ChatMessage } from "./types";

function App() {
  const [rooms, setRooms] = useState<Room[]>([]);
  const [user, setUser] = useState<string | null>(() => localStorage.getItem("chatUser"));
  const [userProfile, setUserProfile] = useState<any>(() => {
    const saved = localStorage.getItem("chatProfile");
    return saved ? JSON.parse(saved) : null;
  });
  const [usernameInput, setUsernameInput] = useState("");
  const [passwordInput, setPasswordInput] = useState("");
  const [currentRoom, setCurrentRoom] = useState<Room | null>(null);
  const [messages, setMessages] = useState<ChatMessage[]>([]);
  const [wsKey, setWsKey] = useState(0);
  const [wsStatus, setWsStatus] = useState<string>("connecting");

  const ws = useRef<WebSocket | null>(null);
  const currentRoomRef = useRef<Room | null>(null);
  const intentionalClose = useRef(false);

  const handleLogin = async () => {
    try {
      const res = await fetch("/auth/login", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ username: usernameInput, password: passwordInput }),
      });
      if (!res.ok) { alert("Invalid credentials"); return; }
      const profile = await res.json();
      localStorage.setItem("chatUser", profile.username);
      localStorage.setItem("chatProfile", JSON.stringify(profile));
      setUserProfile(profile);
      setUser(profile.username);
    } catch (err) {
      alert("Login failed");
    }
  };

  const fetchSubscribedRooms = async (username: string) => {
    try {
      const res = await fetch(`/rooms/subscribed/${username}`);
      const data = await res.json();
      setRooms(data.map((r: any) => ({ id: r._id, topic: r.name, ...r })));
      const saved = localStorage.getItem("chatRoom");
      if (saved) {
        const found = data.find((r: any) => r._id === saved);
        if (found) {
          const room = { id: found._id, topic: found.name, ...found };
          setCurrentRoom(room);
          currentRoomRef.current = room;
        }
      }
    } catch (err) {
      console.error("Failed to fetch subscribed rooms:", err);
    }
  };

  useEffect(() => {
    if (!user) return;
    fetchSubscribedRooms(user);
    const interval = setInterval(() => fetchSubscribedRooms(user), 10000);
    return () => clearInterval(interval);
  }, [user]);

  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const token = params.get("invite");
    if (!token) return;

    const handleInvite = async (username: string) => {
      try {
        const infoRes = await fetch(`/invite/${token}`);
        if (!infoRes.ok) { console.error("Invalid invite"); return; } 
        const { room, invitedUsername } = await infoRes.json();

        if (invitedUsername !== username) {
          alert(`This invite is for user "${invitedUsername}". Please log in as that user.`);
          return;
        }

        const acceptRes = await fetch(`/invite/${token}/accept`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ username }),
        });

        if (acceptRes.ok) {
          window.history.replaceState({}, "", window.location.pathname);
          await fetchSubscribedRooms(username);
          const newRoom = { id: room._id, topic: room.name, ...room };
          setCurrentRoom(newRoom);
          currentRoomRef.current = newRoom;
          localStorage.setItem("chatRoom", room._id);
        }
      } catch (err) {
        console.error("Failed to handle invite:", err);
      }
    };

    if (user) {
      handleInvite(user);
    } else {
      localStorage.setItem("pendingInvite", token);
    }
  }, [user]);

  useEffect(() => {
    const handleVisibilityChange = () => {
      if (document.visibilityState === "visible") {
        intentionalClose.current = false;
        setWsKey((k) => k + 1);
      }
    };
    document.addEventListener("visibilitychange", handleVisibilityChange);
    return () => document.removeEventListener("visibilitychange", handleVisibilityChange);
  }, []);

  useEffect(() => {
    if (!user) return;
    intentionalClose.current = false;
    const proto = window.location.protocol === "https:" ? "wss" : "ws";
    const socket = new WebSocket(`${proto}://${window.location.host}`);
    ws.current = socket;

    socket.onopen = () => {
      setWsStatus("connected");
      if (currentRoomRef.current) {
        socket.send(JSON.stringify({ type: "join", roomId: currentRoomRef.current.id }));
        fetch(`/messages/${currentRoomRef.current.id}`)
          .then(r => r.json())
          .then(msgs => setMessages(msgs))
          .catch(console.error);
      }
    };

    socket.onmessage = (event) => {
      try {
        const msg: ChatMessage & { roomId: string } = JSON.parse(event.data);
        if (currentRoomRef.current && msg.roomId === currentRoomRef.current.id) {
          setMessages((prev) => [...prev, msg]);
        }
      } catch (e) {
        console.error("Failed to parse WS message:", e);
      }
    };

    socket.onclose = (event) => {
      setWsStatus(`closed (${event.code})`);
      if (!intentionalClose.current) {
        setTimeout(() => setWsKey((k) => k + 1), 2000);
      }
      intentionalClose.current = false;
    };

    socket.onerror = (e) => console.error("WebSocket error", e);

    return () => {
      intentionalClose.current = true;
      socket.onclose = null;
      socket.close();
    };
  }, [user, wsKey]);

  const handleSend = (text: string) => {
    if (!currentRoom || !ws.current || !user) return;
    ws.current.send(JSON.stringify({
      roomId: currentRoom.id,
      user,
      text,
      ts: Date.now(),
    }));
  };

  const handleRoomSelect = async (room: Room) => {
    setCurrentRoom(room);
    currentRoomRef.current = room;
    localStorage.setItem("chatRoom", room.id);
    if (ws.current?.readyState === WebSocket.OPEN) {
      ws.current.send(JSON.stringify({ type: "join", roomId: room.id }));
    } else {
      ws.current?.addEventListener("open", () => {
        ws.current?.send(JSON.stringify({ type: "join", roomId: room.id }));
      }, { once: true });
    }
    try {
      const res = await fetch(`/messages/${room.id}`);
      const msgs: ChatMessage[] = await res.json();
      setMessages(msgs);
    } catch (err) {
      setMessages([]);
    }
  };

  const handleRoomsUpdate = () => {
    if (user) fetchSubscribedRooms(user);
  };

  const handleProfileUpdate = (profile: any) => {
    setUserProfile(profile);
    localStorage.setItem("chatProfile", JSON.stringify(profile));
  };

  const handleSignOut = () => {
    localStorage.clear();
    window.location.reload();
  };

  if (!user) {
    return (
      <div className="min-h-screen bg-gray-100 flex items-center justify-center">
        <div className="bg-white rounded-2xl shadow-xl p-8 w-full max-w-sm">
          <div className="flex items-center gap-3 mb-8">
            <div className="w-10 h-10 rounded-xl bg-teal-500 flex items-center justify-center">
              <svg viewBox="0 0 24 24" className="w-6 h-6 fill-white">
                <path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"/>
              </svg>
            </div>
            <div>
              <h1 className="text-lg font-semibold text-gray-900">KafkaChat</h1>
              <p className="text-xs text-gray-400">Sign in to continue</p>
            </div>
          </div>
          <div className="space-y-4">
            <div>
              <label className="text-xs font-medium text-gray-600 uppercase tracking-wide block mb-1">Username</label>
              <input
                className="w-full px-3 py-2.5 border border-gray-200 rounded-lg text-sm focus:outline-none focus:border-teal-500 focus:ring-1 focus:ring-teal-500 bg-gray-50"
                placeholder="Enter username"
                value={usernameInput}
                onChange={(e) => setUsernameInput(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && handleLogin()}
              />
            </div>
            <div>
              <label className="text-xs font-medium text-gray-600 uppercase tracking-wide block mb-1">Password</label>
              <input
                className="w-full px-3 py-2.5 border border-gray-200 rounded-lg text-sm focus:outline-none focus:border-teal-500 focus:ring-1 focus:ring-teal-500 bg-gray-50"
                type="password"
                placeholder="Enter password"
                value={passwordInput}
                onChange={(e) => setPasswordInput(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && handleLogin()}
              />
            </div>
            <button
              onClick={handleLogin}
              className="w-full py-2.5 bg-teal-500 hover:bg-teal-600 active:bg-teal-700 text-white rounded-lg text-sm font-medium transition-colors"
            >
              Sign In
            </button>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="flex h-screen bg-white overflow-hidden">
      <div className={`fixed top-3 right-3 w-2 h-2 rounded-full z-50 transition-colors ${wsStatus === "connected" ? "bg-teal-500" : "bg-red-400"}`} />
      <Sidebar
        rooms={rooms}
        currentRoomId={currentRoom?.id || null}
        onSelect={handleRoomSelect}
        currentUser={user}
        userProfile={userProfile}
        onSignOut={handleSignOut}
        onProfileUpdate={handleProfileUpdate}
        onRoomsUpdate={handleRoomsUpdate}
      />
      <ChatPanel
        room={currentRoom}
        messages={messages}
        onSend={handleSend}
        currentUser={user}
        userProfile={userProfile}
      />
    </div>
  );
}

export default App;
