import { Request, Response } from "express";
import bcrypt from "bcryptjs";

import { prisma } from "../../data/postgres/index.js";
import { JwtAdapter } from "../../config/jwt.js";
import { LoginUserDto, RegisterUserDto } from "../../domain/dtos/index.js";
import { AuthRequest } from "../middlewares/auth.middleware.js";

export class AuthController {

    // SIN metodos estaticos para hacer DI
    constructor() {}

    public registerUser = async (req: Request, res: Response) => {

        const [error, registerUserDto] = RegisterUserDto.create(req.body);

        if (error) {
            return res.status(400).json({ error });
        }

        try {
            const userExists = await prisma.user.findUnique({
                where: {
                    email: registerUserDto!.email,
                }
            });

            if (userExists) {
                return res.status(400).json({
                    error: 'Email already exists'
                });
            }

            const hashedPassword = bcrypt.hashSync(registerUserDto!.password, 10);

            const user = await prisma.user.create({
                data: {
                    name: registerUserDto!.name,
                    email: registerUserDto!.email,
                    password: hashedPassword,
                }
            });

            const token = JwtAdapter.generateToken({
                id: user.id,
                email: user.email,
                role: user.role,
            });

            return res.status(201).json({
                user: {
                    id: user.id,
                    name: user.name,
                    email: user.email,
                    role: user.role,
                },
                token
            });

        } catch (error) {
            console.log(error);
            return res.status(500).json({
                error: 'Internal server error'
            });
        }
    }

    public loginUser = async (req: Request, res: Response) => {

        const [error, loginUserDto] = LoginUserDto.create(req.body);

        if (error) {
            return res.status(400).json({ error });
        }

        try {
            const user = await prisma.user.findUnique({
                where: {
                    email: loginUserDto!.email,
                }
            });

            if (!user) {
                return res.status(400).json({
                    error: 'Invalid email or password'
                });
            }

            const isPasswordValid = bcrypt.compareSync(
                loginUserDto!.password,
                user.password
            );

            if (!isPasswordValid) {
                return res.status(400).json({
                    error: 'Invalid email or password'
                });
            }

            const token = JwtAdapter.generateToken({
                id: user.id,
                email: user.email,
                role: user.role,
            });

            return res.json({
                user: {
                    id: user.id,
                    name: user.name,
                    email: user.email,
                    role: user.role,
                },
                token
            });

        } catch (error) {
            console.log(error);
            return res.status(500).json({
                error: 'Internal server error'
            });
        }
    }

    public getMe = async (req: AuthRequest, res: Response) => {

        if (!req.user) {
            return res.status(401).json({
                error: 'User not authenticated'
            });
        }

        return res.json({
            user: req.user
        });
    }
}