import { ResultAsync, errAsync, okAsync } from "neverthrow";
import type { User } from "@pkg/logic/domains/user/data";
import { user as userStore } from "$lib/global.stores";
import { rotatePasswordSC } from "./account.remote";
import { authClient } from "$lib/auth.client";
import type { Err } from "@pkg/result";
import { toast } from "svelte-sonner";
import { get } from "svelte/store";

class AccountViewModel {
    loading = $state(false);
    passwordLoading = $state(false);
    errorMessage = $state<string | null>(null);

    async updateProfilePicture(imagePath: string): Promise<boolean> {
        const result = await ResultAsync.fromPromise(
            authClient.updateUser({ image: imagePath }),
            (error): Err => ({
                code: "NETWORK_ERROR",
                message: "Failed to update profile picture",
                description: "Network request failed",
                detail: error instanceof Error ? error.message : String(error),
            }),
        ).andThen((response) => {
            if (response.error) {
                return errAsync({
                    code: "API_ERROR",
                    message:
                        response.error.message ??
                        "Failed to update profile picture",
                    description:
                        response.error.statusText ?? "Please try again later",
                    detail: response.error.statusText ?? "Unknown error",
                });
            }
            return okAsync(response.data);
        });

        return result.match(
            () => {
                toast.success("Profile picture updated");
                return true;
            },
            (error) => {
                this.errorMessage =
                    error.message ?? "Failed to update profile picture";
                toast.error(this.errorMessage, {
                    description: error.description,
                });
                return false;
            },
        );
    }

    async updateProfile(userData: {
        name: string;
        username: string;
    }): Promise<User | null> {
        this.loading = true;
        this.errorMessage = null;

        const result = await ResultAsync.fromPromise(
            authClient.updateUser({
                displayUsername: userData.username,
                username: userData.username,
                name: userData.name,
            }),
            (error): Err => ({
                code: "NETWORK_ERROR",
                message: "Failed to update profile",
                description: "Network request failed",
                detail: error instanceof Error ? error.message : String(error),
            }),
        ).andThen((response) => {
            if (response.error) {
                return errAsync({
                    code: "API_ERROR",
                    message:
                        response.error.message ?? "Failed to update profile",
                    description:
                        response.error.statusText ?? "Please try again later",
                    detail: response.error.statusText ?? "Unknown error",
                });
            }
            return okAsync(response.data);
        });

        const user = result.match(
            (data) => {
                toast.success("Profile updated successfully");
                window.location.reload();
                return (data as any)?.user as User | null;
            },
            (error) => {
                this.errorMessage = error.message ?? "Failed to update profile";
                toast.error(this.errorMessage, {
                    description: error.description,
                });
                return null;
            },
        );

        this.loading = false;
        return user;
    }

    async changePassword(password: string): Promise<boolean> {
        this.passwordLoading = true;
        this.errorMessage = null;

        const currentUser = get(userStore);
        if (!currentUser?.id) {
            this.passwordLoading = false;
            this.errorMessage = "User not found";
            toast.error(this.errorMessage);
            return false;
        }
        const result = await ResultAsync.fromPromise(
            rotatePasswordSC({ userId: currentUser.id, password }),
            (error): Err => ({
                code: "NETWORK_ERROR",
                message: "Failed to change password",
                description: "Network request failed",
                detail: error instanceof Error ? error.message : String(error),
            }),
        ).andThen((apiResult: any) => {
            if (apiResult?.error) {
                return errAsync(apiResult.error);
            }
            return okAsync(apiResult?.data);
        });

        const success = result.match(
            () => {
                toast.success("Password updated successfully");
                return true;
            },
            (error) => {
                this.errorMessage =
                    (error.message as string) ?? "Failed to change password";
                toast.error(this.errorMessage, {
                    description: error.description,
                });
                return false;
            },
        );

        this.passwordLoading = false;
        return success;
    }
}

export const accountVM = new AccountViewModel();
