import {onAuthStateChanged, signInWithEmailAndPassword} from "firebase/auth";
import {httpsCallable} from "firebase/functions";
import {SetStateAction} from "react";
import {getUser} from "./readDatabase";
import {ExternalEvent, UserData} from "../typeDefinitions";
import FirebaseQuery from "./firebaseQuery";
import {auth, functions} from "./firebaseConfig";
import {addJob, Job, updateJob} from "../features/jobs/jobsSlice";
import { useAppDispatch } from "../reduxHooks";


export const authListener = (setUser: SetStateAction<any>) => {
    return onAuthStateChanged(auth, (aUser) => {
        if (!aUser) {
            console.log("User not logged in.");
            setUser(false)
            return;
        }
        console.log("User logged in.");
        if (!aUser.email) {
            setUser(false);
            return;
        };
        getUser(aUser.uid, setUser);
    });
};

export const login = async (credentials: {email: string, password: string}) => {
    return await signInWithEmailAndPassword(auth, credentials.email, credentials.password);
};

export type RegistrationData = {
    email: string,
    passwordOne: string,
    instituteName: string,
    "address-line1": string,
    "address-line2": string,
    locality: string,
    postal_code: string,
    country: string,
    first_name: string,
    family_name: string
}

export const register = async (credentials: RegistrationData, type:"Institute"|"Provider"|"Student") => {
    return await executeCallable(`registration-register${type}`, credentials).catch((e) => {
        console.log("Error in regsiter", e);
        throw e;
    }).then(async (res) => {
        if (type === "Student") {
            await login({email: credentials.email, password: credentials.passwordOne});
        }
        return (res.data as { msg: {uid: string}}).msg.uid as string;
    });
};

export const executeCallable = async (functionName: string, data: unknown) => {
    const funcCallable = httpsCallable(functions, functionName);
    const res = await funcCallable(data).catch((e) => {
        console.log("callableError", functionName, e);
        throw e;
    });

    return res as {data: any};
};


export function useExecuteCallableJob({user}:{user: UserData}) {
    type CallableFunctionJobs = "userManagement-addUsers"|"userManagement-activateUsers"|
    "userManagement-deactivateUsers"|"userManagement-deleteUsers"|"admissions-createCohort"|"userManagement-uploadAnalytics"|
    "providerContacts-add"|"userManagement-sendParentWelcomeEmail"|"events-sendExternalEventInvites"|"events-sendEmployerConfirmations"|
    "placementListing-addToCohort"|"placementListing-delist"|"providerContacts-delete"|"events-addStudents"|"registration-registerInstitutes"|
    "events-careersHubAddSchool"|"events-studentJoinEvent"|"events-addStudents"|"userManagement-addStudentsToCohort"|"userManagement-removeFromCohort"
    const dispatch = useAppDispatch();

    const execute = async (functionName:CallableFunctionJobs, data:{[key:string]:unknown}) => {
        const getCode = () => {
            switch (functionName) {
            case "userManagement-addUsers":
                return {
                    title: "Add users",
                    description: `Adding ${(data as {users:unknown[]}).users.length} ${(data as {userType:string}).userType.toLowerCase()}`,
                };
            case "userManagement-activateUsers":
                return {
                    title: "Activating users",
                    description: `Attempting activation of ${Array.isArray((data as {users:{[key:string]:unknown}}).users) ?
                        "multiple" : Object.entries((data as {users:{[key: string]: UserData}}).users).length} users.`,
                };
            case "userManagement-deactivateUsers":
                return {
                    title: "Deactivating users",
                    description: `Deactivating ${Array.isArray((data as {users:{[key:string]:unknown}}).users) ?
                        "multiple" : Object.entries((data as {users:{[key: string]: UserData}}).users).length || "multiple"} users.`,
                };
            case "userManagement-removeFromCohort":
                return {
                    title: "Removing users from cohort",
                    description: `Removing ${Array.isArray((data as {users:{[key:string]:unknown}}).users) ?
                        "multiple" : Object.entries((data as {users:{[key: string]: UserData}}).users).length || "multiple"} users from your cohort.`,
                };
            case "userManagement-deleteUsers":
                return {
                    title: "Deleting users",
                    description: `Attempting deletion of ${Array.isArray((data as {users:{[key:string]:unknown}}).users) ?
                        "multiple" : Object.entries((data as {users:{[key: string]: UserData}}).users).length || "multiple"} users.`,
                };
            case "providerContacts-add":
                return {
                    title: "Adding employer contacts",
                    description: `Attempting addition of ${(data as {providerContacts:[]}).providerContacts.length} employer contacts`,
                };
            case "userManagement-sendParentWelcomeEmail":
                return {
                    title: "Sending parent welcome emails",
                    description: `Sending parent welcome emails to ${Array.isArray((data as {users:{[key:string]:unknown}}).users) ?
                        "multiple" : Object.entries((data as {users:{[key: string]: UserData}}).users).length || "multiple"} users.`,
                };
            case "events-sendExternalEventInvites":
                return {
                    title: `Sending email invites for event: ${(data as {data:{eventName: string}}).data.eventName}`,
                    description: `Sending email invites for your event: '${(data as {data:{eventName: string}}).data.eventName}'. Check the event page to view email interactions.`,
                };
            case "events-sendEmployerConfirmations":
                return {
                    title: `Sending employer confirmation emails for event: ${(data as {data: {event: Partial<ExternalEvent>}}).data.event.name}`,
                    description: `Sending employer confirmation emails for your event: '${(data as {data: {event: Partial<ExternalEvent>}}).data.event.name}' to ${(data as {data: {selectedEmployers: {
                allSelected: boolean;
                search: string | undefined;
                filters: unknown[][] | undefined;
            }|{[key: string]: unknown}}}).data.selectedEmployers.allSelected ? "all employers" : `${Object.keys((data as {data: {selectedEmployers: {
                allSelected: boolean;
                search: string | undefined;
                filters: unknown[][] | undefined;
            }|{[key: string]: unknown}}}).data.selectedEmployers).length} employers`}. Check the event page to view email interactions.`,
                };
            case "events-addStudents":
                return {
                    title: `Adding students to event event: ${(data as {event:Partial<ExternalEvent>}).event.name}`,
                    description: `Sending student email invites for your event: '${(data as {event:Partial<ExternalEvent>}).event.name}'. Check the event page to view email interactions.`,
                };
            case "placementListing-addToCohort":
                return {
                    title: "Adding placement listings to cohort",
                    description: "Students will be able to view all listings you add.",
                };
            case "placementListing-delist":
                return {
                    title: "Delisting placement listings from cohort",
                    description: "Students will not be able to view selected listings.",
                };
            case "providerContacts-delete":
                return {
                    title: "Deleting provider contacts from database",
                    description: "You will no longer have access to these contacts.",
                };
            case "registration-registerInstitutes":
                return {
                    title: `Inviting ${(data as {schools: {}[]}).schools.length} school${(data as {schools: {}[], type: "hub"|"trust"}).schools.length === 1 ? "" : "s"} to your ${(data as {schools: {}[], type: "hub"|"trust"}).type === "hub" ? "Careers Hub" : "trust"}`,
                    description: `Sending invites to ${(data as {schools: {}[]}).schools.length} school${(data as {schools: {}[]}).schools.length === 1 ? "" : "s"}. Check back later for responses.`,
                };
            case "events-careersHubAddSchool":
                const schoolData = data.schools as {groups?: string[], schools?: "all"|string[]};
                const text:string[] = [];
                if (schoolData.schools){
                    text.push(`${schoolData.schools.length} school${schoolData.schools.length === 1 ? "" : "s"}`);
                }
                if (schoolData.groups && schoolData.groups.length){
                    text.push(`${schoolData.groups.length} school group${schoolData.groups.length === 1 ? "" : "s"}`);
                }
                return {
                    title: `Inviting ${text.join(" and ")} to your event`,
                    description: `Sending invites to ${text.join(" and ")}. Check back later for responses.`,
                };
            case "events-studentJoinEvent":
                return {
                    title: "Adding students to your event",
                    description: "Sending invites to students. Check back later for responses.",
                };
            case "events-addStudents":
                return {
                    title: "Adding students to your event",
                    description: "Sending invites to students. Check back later for responses.",
                };
            case "userManagement-addStudentsToCohort":
                return {
                    title: "Adding students to your cohort",
                    description: "Students will appear in the students tab of your cohort once complete.",
                };
            default:
                return;
            }
        };

        const date = new Date();
        const firebaseQuery = new FirebaseQuery();

        const jobObject = {
            title: getCode()?.title,
            description: getCode()?.description,
            status: "processing",
            viewedBy: [],
            started: date.toISOString(),
            updated: date.toISOString(),
            oId: user.oId,
            product: user.product,
        };

        const jobId = (await firebaseQuery.add(["jobs"], jobObject)).id;

        console.log("jobId", jobId);
        dispatch(addJob({
            jobId: jobId,
            job: jobObject,
        }));

        const items = {...data, jobId: jobId};

        const funcCallable = httpsCallable(functions, functionName);
        console.log(items);
        funcCallable(items).then(async () => {
            const jobResolved = await firebaseQuery.getDocData(["jobs", jobId]) as Job;
            dispatch(updateJob({
                jobId: jobId,
                data: jobResolved
            } as Partial<Job>));
        });
        return {
            severity: "success",
            message: "Waiting on database. Check the orange progress icon on the top right of the screen. Once completed, you may need to reload the page.",
            jobId: jobId,
        };
    };

    return {execute};
}
