import { FastifyReply, FastifyRequest } from 'fastify';
import * as userService from './user.service';
import {queryOne} from '../../shared/database';
import jwt from "jsonwebtoken";

interface UserIdParams { id: string; }
interface CreateUserBody {
    username: string;
    profilePictureUrl?: string;
    password?: string;
}
interface UpdateUserBody {
    username?: string;
    profilePictureUrl?: string | null;
    password?: string | null;
}
interface LoginBody {
    userId: number;
    password?: string;
}

interface DBRunResult { changes: number; lastID: number; }

export async function getMe(req: any, reply: any) {
    const userId = req.user?.id;

    if (!userId) {
        return reply.code(401).send({ error: "Unauthorized" });
    }

    const user = await queryOne(
        `SELECT username, profile_picture_url FROM User WHERE id = ?`,
        [userId],
        'userdata'
    );

    if (!user) {
        return reply.code(404).send({ error: "User not found" });
    }

    return reply.send({
        username: user.username,
        avatar: user.profile_picture_url
    });
}

export async function login(req: FastifyRequest, reply: FastifyReply) {
    const { userId, password } = req.body as LoginBody;

    if (!userId || typeof userId !== "number" || userId <= 0) {
        return reply.code(400).send({ error: "Invalid userId provided" });
    }

    const user = await userService.getUserById(userId);

    if (!user) {
        return reply.code(404).send({ error: "User not found in local database" });
    }

    // Si el usuario tiene contraseña, debe proporcionarla
    if (user.has_password) {
        if (!password) {
            return reply.code(401).send({
                error: "Password required",
                requiresPassword: true
            });
        }

        const isValid = await userService.verifyPassword(userId, password);

        if (!isValid) {
            return reply.code(401).send({ error: "Incorrect password" });
        }
    }

    const token = jwt.sign(
        { id: userId },
        process.env.JWT_SECRET!,
        { expiresIn: "7d" }
    );

    return reply.code(200).send({
        success: true,
        token
    });
}

export async function getAllUsers(req: FastifyRequest, reply: FastifyReply) {
    try {
        const users: any = await userService.getAllUsers();
        return { users };
    } catch (err) {
        console.error("Get All Users Error:", (err as Error).message);
        return reply.code(500).send({ error: "Failed to retrieve user list" });
    }
}

export async function createUser(req: FastifyRequest, reply: FastifyReply) {
    try {
        const { username, profilePictureUrl, password } = req.body as CreateUserBody;

        if (!username) {
            return reply.code(400).send({ error: "Missing required field: username" });
        }

        const result: any = await userService.createUser(username, profilePictureUrl, password);

        return reply.code(201).send({
            success: true,
            userId: result.lastID,
            username
        });
    } catch (err) {
        if ((err as Error).message.includes('SQLITE_CONSTRAINT')) {
            return reply.code(409).send({ error: "Username already exists." });
        }
        console.error("Create User Error:", (err as Error).message);
        return reply.code(500).send({ error: "Failed to create user" });
    }
}

export async function getUser(req: FastifyRequest, reply: FastifyReply) {
    try {
        const { id } = req.params as UserIdParams;
        const userId = parseInt(id, 10);

        const user: any = await userService.getUserById(userId);

        if (!user) {
            return reply.code(404).send({ error: "User not found" });
        }

        return { user };
    } catch (err) {
        console.error("Get User Error:", (err as Error).message);
        return reply.code(500).send({ error: "Failed to retrieve user" });
    }
}

export async function updateUser(req: FastifyRequest, reply: FastifyReply) {
    try {
        const { id } = req.params as UserIdParams;
        const userId = parseInt(id, 10);
        const updates = req.body as UpdateUserBody;

        if (Object.keys(updates).length === 0) {
            return reply.code(400).send({ error: "No update fields provided" });
        }

        const result: DBRunResult = await userService.updateUser(userId, updates);

        if (result && result.changes > 0) {
            return { success: true, message: "User updated successfully" };
        } else {
            return reply.code(404).send({ error: "User not found or nothing to update" });
        }
    } catch (err) {
        if ((err as Error).message.includes('SQLITE_CONSTRAINT')) {
            return reply.code(409).send({ error: "Username already exists or is invalid." });
        }
        console.error("Update User Error:", (err as Error).message);
        return reply.code(500).send({ error: "Failed to update user" });
    }
}

export async function deleteUser(req: FastifyRequest, reply: FastifyReply) {
    try {
        const { id } = req.params as { id: string };
        const userId = parseInt(id, 10);

        const body = (req.body ?? {}) as { password?: string };
        const password = body.password;

        if (!userId || isNaN(userId)) {
            return reply.code(400).send({ error: "Invalid user id" });
        }

        const user = await userService.getUserById(userId);
        if (!user) {
            return reply.code(404).send({ error: "User not found" });
        }

        if (user.has_password) {
            if (!password) {
                return reply.code(401).send({ error: "Password required" });
            }

            const isValid = await userService.verifyPassword(userId, password);
            if (!isValid) {
                return reply.code(401).send({ error: "Incorrect password" });
            }
        }

        const result = await userService.deleteUser(userId);

        if (result.changes > 0) {
            return reply.send({ success: true });
        }

        return reply.code(500).send({ error: "Failed to delete user" });

    } catch (err) {
        console.error("Delete User Error:", err);
        return reply.code(500).send({ error: "Failed to delete user" });
    }
}

export async function getIntegrationStatus(req: FastifyRequest, reply: FastifyReply) {
    try {
        const { id } = req.params as { id: string };
        const userId = parseInt(id, 10);

        if (!userId || isNaN(userId)) {
            return reply.code(400).send({ error: "Invalid user id" });
        }

        const integration = await userService.getAniListIntegration(userId);

        return reply.code(200).send(integration);

    } catch (err) {
        console.error("Get Integration Status Error:", (err as Error).message);
        return reply.code(500).send({ error: "Failed to check integration status" });
    }
}

export async function disconnectAniList(req: FastifyRequest, reply: FastifyReply) {
    try {
        const { id } = req.params as { id: string };
        const userId = parseInt(id, 10);

        if (!userId || isNaN(userId)) {
            return reply.code(400).send({ error: "Invalid user id" });
        }

        const result = await userService.removeAniListIntegration(userId);

        if (result.changes === 0) {
            return reply.code(404).send({ error: "AniList integration not found" });
        }

        return reply.send({ success: true });
    } catch (err) {
        console.error("Disconnect AniList Error:", err);
        return reply.code(500).send({ error: "Failed to disconnect AniList" });
    }
}

export async function changePassword(req: FastifyRequest, reply: FastifyReply) {
    try {
        const { id } = req.params as { id: string };
        const { currentPassword, newPassword } = req.body as {
            currentPassword?: string;
            newPassword: string | null;
        };
        const userId = parseInt(id, 10);

        if (!userId || isNaN(userId)) {
            return reply.code(400).send({ error: "Invalid user id" });
        }

        const user = await userService.getUserById(userId);

        if (!user) {
            return reply.code(404).send({ error: "User not found" });
        }

        if (user.has_password) {
            if (!currentPassword) {
                return reply.code(401).send({ error: "Current password required" });
            }

            const isValid = await userService.verifyPassword(userId, currentPassword);
            if (!isValid) {
                return reply.code(401).send({ error: "Current password is incorrect" });
            }
        }

        await userService.updateUser(userId, { password: newPassword });

        return reply.send({
            success: true,
            message: newPassword ? "Password updated successfully" : "Password removed successfully"
        });
    } catch (err) {
        console.error("Change Password Error:", err);
        return reply.code(500).send({ error: "Failed to change password" });
    }
}