import { createCookieSessionStorage, redirect } from "@remix-run/node";
import bcrypt from "bcryptjs";
import { prisma } from "~/utils/db.server";

// Session storage
const sessionSecret = process.env.SESSION_SECRET || "default-secret";
const { getSession, commitSession, destroySession } = createCookieSessionStorage({
    cookie: {
        name: "__session",
        httpOnly: true,
        maxAge: 60 * 60 * 24 * 7, // 7 days
        path: "/",
        sameSite: "lax",
        secrets: [sessionSecret],
        secure: process.env.NODE_ENV === "production",
    },
});

export { getSession, commitSession, destroySession };

// Auth functions
export async function createUserSession(userId: number, redirectTo: string) {
    const session = await getSession();
    session.set("userId", userId);
    return redirect(redirectTo, {
        headers: {
            "Set-Cookie": await commitSession(session),
        },
    });
}

export async function getUserSession(request: Request) {
    return getSession(request.headers.get("Cookie"));
}

export async function getUserId(request: Request) {
    const session = await getUserSession(request);
    const userId = session.get("userId");
    if (!userId || typeof userId !== "number") return null;
    return userId;
}

export async function requireUserId(request: Request, redirectTo: string = "/signin") {
    const userId = await getUserId(request);
    if (!userId) {
        const searchParams = new URLSearchParams([["redirectTo", new URL(request.url).pathname]]);
        throw redirect(`${redirectTo}?${searchParams}`);
    }
    return userId;
}

export async function getUser(request: Request) {
    const userId = await getUserId(request);
    if (!userId) return null;

    try {
        const user = await prisma.employee.findUnique({
            where: { id: userId },
            select: { id: true, name: true, username: true, email: true, authLevel: true, status: true },
        });

        // If user is inactive, logout and return null
        if (user && user.status === 'inactive') {
            throw logout(request);
        }

        return user;
    } catch {
        throw logout(request);
    }
}

export async function requireUser(request: Request) {
    const user = await getUser(request);
    if (!user) {
        throw redirect("/signin");
    }
    return user;
}

export async function requireAuthLevel(request: Request, minLevel: number = 2) {
    const user = await requireUser(request);
    if (user.authLevel < minLevel) {
        throw redirect("/signin");
        //throw new Response("Unauthorized", { status: 403 });
        // redirect to dashboard page
        //redirect("/dashboard");
    }
    return user;
}

export async function logout(request: Request) {
    const session = await getUserSession(request);
    return redirect("/signin", {
        headers: {
            "Set-Cookie": await destroySession(session),
        },
    });
}

export async function verifyLogin(usernameOrEmail: string, password: string) {
    // Try to find user by username first, then by email
    const user = await prisma.employee.findFirst({
        where: {
            OR: [
                { username: usernameOrEmail },
                { email: usernameOrEmail }
            ]
        }
    });

    if (!user || !bcrypt.compareSync(password, user.password)) {
        return null;
    }

    // Check if user is inactive
    if (user.status === 'inactive') {
        return null;
    }

    return { id: user.id, username: user.username, email: user.email, name: user.name, authLevel: user.authLevel, status: user.status };
}

export async function createUser(name: string, username: string, email: string, password: string, authLevel: number = 1) {
    const hashedPassword = bcrypt.hashSync(password, 10);

    const user = await prisma.employee.create({
        data: {
            name,
            username,
            email,
            password: hashedPassword,
            authLevel,
            status: 'active',
        },
    });

    return { id: user.id, username: user.username, email: user.email, name: user.name, authLevel: user.authLevel, status: user.status };
}