import React, { createContext, useContext, useState, useEffect, ReactNode } from "react";
import { User, Role } from "../types/user";
import api from "../utils/api";

interface Credentials {
    username: string;
    password: string;
}

interface UserContextType {
    user: User | null;
    isLoggedIn: boolean;
    loginWithCredentials: (credentials: Credentials) => Promise<void>;
    logout: () => void;
    updateUserPP: (profilePicture: string) => void; // profile picture update function
    updateBio: (bio: string) => void; // bio update function
}

const UserContext = createContext<UserContextType | undefined>(undefined);

export const UserProvider = ({ children }: { children: ReactNode }) => {
    const [user, setUser] = useState<User | null>(null);


    const setUserFromBackendData = async (backendUser: any, role: string) => {

        const userData: User = {
            id: backendUser.id,
            username: backendUser.username,
            email: backendUser.email,
            bio: backendUser.bio || '',
            role: role || Role.USER, // for some reason, backendUser.roles is an array with one element, but we need a string
            // apparently, it is due to the fact that the backend is using a library that returns an array of roles... Nette...
            profilePicture: import.meta.env.VITE_PROFILE_PICTURES_URL + (backendUser.profile_image || '')
        };

        setUser(userData);
    };

    const loginWithCredentials = async (credentials: Credentials) => {

        await api.post('/user/login', credentials).then(async res => {
            await setUserFromBackendData(res.data.user, res.data.roles[0]);
        }).catch(error => {
            if (error.response?.status === 401) {
                alert("Neplatné uživatelské jméno nebo heslo");
            }

            else if (error.response?.status === 409) {
                alert("Účet s uživatelským jménem nebo emailem již existuje");
            }

            else {
                alert("Nastala chyba při přihlašování");

            }
        });
    }


    const logout = async () => {
        try {
            await api.post("/user/logout");
            setUser(null);
        } catch (error) {
            console.error("Chyba při odhlášení:", error);
        }
    };

    const isLoggedIn = !!user;

    const updateUserPP = (newUrl: string) => {
        setUser(prev => prev ? { ...prev, profilePicture: newUrl } : prev);
    };

    const updateBio = (bio: string) => {
        setUser(prev => prev ? { ...prev, bio: bio } : prev);
    }

    useEffect(() => {
        const fetchUserOnMount = async () => {
            try {
                const res = await api.get('/user/getuser');
                await setUserFromBackendData(res.data.user, res.data.roles[0]);
            } catch (error: any) {
                if (error.response?.status === 401) {
                    console.log("Uživatel není přihlášen (session neexistuje)");
                } else {
                    console.error("Chyba při získávání session uživatele:", error);
                }
            }
        };

        fetchUserOnMount();
    }, []);

    return (
        <UserContext.Provider value={{ user, isLoggedIn, loginWithCredentials, logout, updateUserPP, updateBio }}>
            {children}
        </UserContext.Provider>
    );
};

export const useUser = () => {
    const context = useContext(UserContext);
    if (!context) {
        throw new Error("useUser must be used within a UserProvider");
    }
    return context;
};
