import {createContext, useContext,
        useState, useEffect, 
        useRef
        } from "react";
import { API_BASE } from "../config";

const HotelContext = createContext(null);



export function useHotel() {
  return useContext(HotelContext);
}

export function HotelProvider({ accessToken, children, resClientId}) {
    const [rooms, setRooms] = useState([]);
    const [conversations, setConversations] = useState([]);
    const [messagesByConvId, setMessagesByConvId] = useState({});

    const [users, setUsers] = useState([]);
    const [usersById, setUsersById] = useState({});
    const [clientId, setClientId] = useState(resClientId|| null);

    const tokens = JSON.parse(accessToken);
    const accessTokenSingle = tokens[0];

    const wsRef = useRef(null);


  // --- API FUNCTIONS ---
 
//   ROOMS

  async function fetchRooms() {
    const res = await fetch( `${API_BASE}/rooms/rooms`, {
      headers: { Authorization: `Bearer ${accessTokenSingle}` },
    });
    return res.json();
  }

  async function updateRoomStatus(roomId, status) {
    await fetch(`${API_BASE}/rooms/clean_db_update/${roomId}`, {
      method: "PUT",
      headers: {
        Authorization: `Bearer ${accessTokenSingle}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ status }),
    });

    // refresh cached rooms
    //const updated = await fetchRooms();
    //setRooms(updated);
  }
  
//   CHAT


  async function createConversation(name) {
    
    const payload = {
      name
    };

    const res = await fetch(`${API_BASE}/chat/create_conversation`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessTokenSingle}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });
  
  }

  function appendMessage(msg) {
  setMessagesByConvId(prev => ({
    ...prev,
    [msg.conv_id]: [
      ...(prev[msg.conv_id] ?? []),
      msg,
    ],
  }));
}

  async function fetchConversations() {
    const res = await fetch(`${API_BASE}/chat/get_conv`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessTokenSingle}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        conv_id: 4,
        timestamp: "2025-09-25 11:05:33",
      }),
    });
    return res.json();
  }

  async function fetchMessages({ conv_id }) {

    const payload = {
    conv_id,
    timestamp: "2025-09-25 11:05:33",
    };

    //console.log(JSON.stringify(payload));

    const res = await fetch(`${API_BASE}/chat/get_message`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessTokenSingle}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });

    const messages = await res.json();

    setMessagesByConvId(prev => ({
    ...prev,
    [conv_id]: messages,

  }));

  return messages;

    
    //return res.json
  }

  async function fetchConvUsers({ conv_id }) {

    const payload = {
    conv_id,
    timestamp: "2025-09-25 11:05:33",
    };

    //console.log(JSON.stringify(payload));

    const res = await fetch(`${API_BASE}/chat/get_conv_users/${conv_id}`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessTokenSingle}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });

    return res.json();
    
    //return res.json
  }

  async function sendMessage({ conv_id, message }) {
    if (!conv_id) {    
      console.log("conv_id null at sendMessage")
      return
    };    

    const payload = {
      conv_id,
      message
    };

    //console.log(JSON.stringify(payload));

    const res = await fetch(`${API_BASE}/chat/send_message`, {
      method: "POST" ,
      headers: {
        Authorization: `Bearer ${accessTokenSingle}`,
        "Content-Type" : "application/json",
      },
      body: JSON.stringify(payload),
    })
  }

  async function addUserToConv({ conv_id, users}) {
    if (!conv_id || !users) {
      console.log("error in convs or user to add")
    };

    const payload = {
      conv_id,
      users
    };

    const res = await fetch(`${API_BASE}/chat/add_users_conv`, {
      method: "PUT" ,
      headers: {
        Authorization: `Bearer ${accessTokenSingle}`,
        "Content-Type" : "application/json",
      },
      body: JSON.stringify(payload),
    })


  }

  async function preloadMessages(conversations) {
  for (const conv of conversations) {
    await fetchMessages({ conv_id: conv.id });
  }
}

//   INVENTORY


  async function fetchHotelInventory() {

    const res = await fetch ( `${API_BASE}/inventory/get_item/`,  {
      headers: { Authorization: `Bearer ${accessTokenSingle}`},
    });

    console.log ("fetched inventory")

    return res.json()

  }

  async function updateItemAmount(item_id, item_amount) {

    const res = await fetch ( `${API_BASE}/inventory/update_item/${item_id}/${item_amount}`, 
      { 
        method: "PUT",
        headers: { Authorization: `Bearer ${accessTokenSingle}` } 
    });

  }

  async function createItem(item_name, item_amount){
    
    const res = await fetch ( `${API_BASE}/inventory/add_item/${item_name}/${item_amount}`,
      {
        method:"POST",
        headers: { Authorization: `Bearer ${accessTokenSingle}` }
      });
  
  }

  async function fetchHotelUsers() {
    const res = await fetch(`${API_BASE}/chat/hotel_users`, {
      method: "POST",
      headers: { 
        Authorization: `Bearer ${accessTokenSingle}`,
        "Content-Type": "application/json", 
      },
    });
    
    const users = await res.json();

    const map = {};
    for (const u of users) {
        map[u.id] = u.username;
    }
    setUsersById(map);

//   setUsers(users)
    return users;
  }

  // --- WS DISPATCH MESSAGE ----



  function handleWsMessage(msg) {
    console.log("websocket message is :" + msg.event_type, typeof msg.event_type);
  switch (msg.event_type) {


    case "room_update": {
      setRooms(prev =>
        prev.map(r =>
          r.id === msg.room_id
            ? { ...r, status: msg.status }
            : r
        )
      );
      break;
    }

    case "chat_message": {
      appendMessage(msg);
      break;
    }

    default:
      console.warn("Unhandled WS message bruuuuh:", msg);
  }
}


  // --- WS USE EFFECT  ----



  // --- INITIAL DATA LOADING ---
  useEffect(() => {
    if (!accessToken) return;

    async function load() {
      const [roomsData, convData, usersData] = await Promise.all([
        fetchRooms(),
        fetchConversations(),
        fetchHotelUsers(),
        
      ]);
      
      setClientId(resClientId);
      setRooms(roomsData);
      setConversations(convData);
      setUsers(usersData);

      

    }
    
    load();

      
    //console.log("USERS 2 =",usersById)
  }, []);

  useEffect(() => {
  if (conversations.length === 0) return;

  preloadMessages(conversations);
}, [conversations]);

    useEffect(() => {
  //if (!accessTokenSingle || !clientId) return;

  const ws = new WebSocket(
    `http://localhost:7080/auth/ws/${accessTokenSingle}`
  );

  wsRef.current = ws;

  ws.onopen = () => {
    console.log("WS connected");
  };

  ws.onmessage = (event) => {
    const msg = JSON.parse(event.data);
    console.log("WS :", msg);

    handleWsMessage(msg);
  };

  ws.onerror = (err) => {
    console.error("WS error", err);
  };

  ws.onclose = () => {
    console.log("WS disconnected");
  };

  return () => {
    ws.close();
  };
}, [accessTokenSingle]);



  return (
    <HotelContext.Provider
      value={{
        rooms,
        conversations,
        messagesByConvId,
        users,
        usersById,
        clientId,
        updateRoomStatus,
        fetchMessages,
        fetchConvUsers,
        sendMessage,
        fetchHotelUsers,
        addUserToConv,
        createConversation,
        fetchHotelInventory,
        updateItemAmount,
        createItem
      }}
    >
      {children}
    </HotelContext.Provider>
  );
}

