import React, { createContext, useContext, useEffect, useState, useCallback } from "react";
import * as sdk from "matrix-js-sdk";

const MatrixContext = createContext(null);

export function useMatrix() {
  return useContext(MatrixContext);
}

export function MatrixProvider({ children }) {
  const [client, setClient] = useState(null);
  const [rooms, setRooms] = useState([]);
  const [messages, setMessages] = useState([]);
  const [user, setUser] = useState(null);
  const [currentRoomId, setCurrentRoomId] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  // Login to Matrix
  const login = useCallback(async (username, password, homeserver = "https://matrix.org") => {
    setLoading(true);
    setError(null);
    try {
      const matrixClient = sdk.createClient({ baseUrl: homeserver });
      const resp = await matrixClient.loginWithPassword(username, password);
      matrixClient.startClient({ initialSyncLimit: 10 });
      setClient(matrixClient);
      setUser({ userId: resp.user_id, accessToken: resp.access_token });
      setLoading(false);
      // Listen for sync and events
      matrixClient.on("sync", (state) => {
        if (state === "PREPARED") {
          setRooms(matrixClient.getRooms());
        }
      });
      matrixClient.on("Room.timeline", (event, room) => {
        if (room.roomId === currentRoomId && event.getType() === "m.room.message") {
          setMessages((msgs) => [...msgs, event.event]);
        }
      });
    } catch (e) {
      setError(e.message);
      setLoading(false);
    }
  }, [currentRoomId]);

  // Join a room and fetch messages
  const joinRoom = useCallback(async (roomId) => {
    if (!client) return;
    setCurrentRoomId(roomId);
    const room = client.getRoom(roomId);
    if (room) {
      setMessages(room.timeline.filter(e => e.getType() === "m.room.message").map(e => e.event));
    }
  }, [client]);

  // Send a message
  const sendMessage = useCallback(async (roomId, text) => {
    if (!client) return;
    await client.sendTextMessage(roomId, text);
  }, [client]);

  return (
    <MatrixContext.Provider value={{ client, rooms, messages, user, login, joinRoom, sendMessage, currentRoomId, loading, error }}>
      {children}
    </MatrixContext.Provider>
  );
}
