"use server";

import {AppwriteException, Databases, ID, Query} from "node-appwrite";
import {createAdminClient} from "@/lib/backend/server-appwrite";
import {
    AppriteActionReturnStatus,
    ClientProfile,
    PatientProfile,
    UserProfile,
    UserType,
} from "@/lib/backend/appwrite_types";
import {AddNewClientProps} from "@/app/(admin)/admin/manage-clients/_components/data";


export async function getUserType(id: string): UserProfile {
    const {client} = await createAdminClient();
    const databases = new Databases(client);
    let response = await databases.listDocuments(
        process.env.NEXT_APPWRITE_DATABASE_ID!,
        process.env.NEXT_APPWRITE_USERS_COLLECTION_ID!,
        [Query.equal('userId', id)],
        1
    )
    if (response.total > 0 && response.documents.length > 0)
        return response.documents[0] as UserProfile
    else
        throw Error("User profile not found.")
}


export async function fetchUserProfile(id: string) {
    const {client} = await createAdminClient();
    const databases = new Databases(client);
    let response = await databases.listDocuments(
        process.env.NEXT_APPWRITE_DATABASE_ID!,
        process.env.NEXT_APPWRITE_USERS_COLLECTION_ID!,
        [Query.equal('userId', id)],
        1
    )
    if (response.total > 0 && response.documents.length > 0)
        return response.documents[0] as UserProfile
    else
        throw Error("User profile not found.")
}

export async function updatePatientProfile(props: Partial<PatientProfile>, userId: string): AppriteActionReturnStatus {

    try {
        const {client} = await createAdminClient();
        const databases = new Databases(client);

        await databases.updateDocument(
            process.env.NEXT_APPWRITE_DATABASE_ID!,
            process.env.NEXT_APPWRITE_PATIENTS_COLLECTION_ID!,
            userId, // same as the profile document id
            props
        );

        return {
            message: "success",
            code: 200
        };

    } catch (e) {
        console.log(e)
        if (e instanceof AppwriteException) {
            return {
                message: e.message,
                code: e.code,
                error: e.response,
            }
        } else {
            return {
                message: "Server error. Try again later.",
                code: 500,
                error: "Failed to signup",
            }
        }
    }
}


export async function createClientProfile(props: AddNewClientProps): AppriteActionReturnStatus {

    try {
        // generate a random password
        const password = ID.unique(0);

        const {client, account, messaging} = await createAdminClient();
        const databases = new Databases(client);

        // create a user account for the client
        const user = await account.create(
            ID.unique(),
            props.email,
            password,
            `${props.first_name} ${props.last_name}`
        );

        // mark user as a client in the users table
        await databases.createDocument(
            process.env.NEXT_APPWRITE_DATABASE_ID!,
            process.env.NEXT_APPWRITE_USERS_COLLECTION_ID!,
            user.$id,
            {
                userId: user.$id,
                userType: UserType.CLIENT,
                fullName: `${props.first_name} ${props.last_name}`
            }
        )

        // then create the client's profile
        await databases.createDocument(
            process.env.NEXT_APPWRITE_DATABASE_ID!,
            process.env.NEXT_APPWRITE_CLIENTS_COLLECTION_ID!,
            user.$id, //ID.unique(),
            {
                userId: user.$id,
                title: props.title,
                firstName: props.first_name,
                lastName: props.last_name,
                email: props.email,
                phoneNumber: props.phone_number,
                emergencyContact: props.emergency_contact,
                physicalAddress: props.physical_address,
                dob: props.dob,
                specializedSkills: props.specialized_skills,
                languages: props.languages,
                nursingLicenceNumber: props.nursing_licence_number,
                qualificationEarned: props.qualification_earned,
                nursingSchool: props.nursing_school,
                graduationDate: props.graduation_date
            }
        );


        // then send an sms with the credentials
        await messaging.createEmail(
            ID.unique(),
            "TheraChat account successfully activated!",
            'Your TheraChat account has been created successfully. Visit https://therachat.co.za/login to access your client portal. You login credentials are: \n\n' +
            `Username: ${props.email}\nPassword: ${password}.\n\n\nChange your password on the first login.`,
            [],
            [],
            [user.targets.at(0).$id],
            [],
            [],
            [],
            false,
            false,
            null,
        )

        // return success
        return {
            message: "success",
            code: 200
        };

    } catch (e) {

        if (e instanceof AppwriteException) {
            let _type: string = ""
            if (e.type === "user_already_exists") _type = "email";

            return {
                message: e.message,
                code: e.code,
                error: e.response,
                type: _type
            }
        } else {
            return {
                message: "Server error. Try again later.",
                code: 500,
                error: "Failed to signup",
            }
        }


    }


}


export async function getAdminDashboardData() {

    const {client} = await createAdminClient();
    const databases = new Databases(client);
    let patientResponse = await databases.listDocuments(
        process.env.NEXT_APPWRITE_DATABASE_ID!,
        process.env.NEXT_APPWRITE_PATIENTS_COLLECTION_ID!,
        [Query.orderDesc("$updatedAt"), Query.limit(8)]
    )

    let clientsResponse = await databases.listDocuments(
        process.env.NEXT_APPWRITE_DATABASE_ID!,
        process.env.NEXT_APPWRITE_CLIENTS_COLLECTION_ID!, []
    )

    return {
        patientResponse,
        clientsResponse
    }
}


export async function getAdminManageClientsData() {

    const {client} = await createAdminClient();
    const databases = new Databases(client);

    const clientsResponse = await databases.listDocuments(
        process.env.NEXT_APPWRITE_DATABASE_ID!,
        process.env.NEXT_APPWRITE_CLIENTS_COLLECTION_ID!,
        [Query.limit(8), Query.orderDesc("$createdAt")]
    )

    return {
        clients: clientsResponse.documents as ClientProfile[],
        total: clientsResponse.total as number
    }
}