/**
 * ==========================================================
 * Smart Attendance System
 * Authentication Service
 * ==========================================================
 */

const AuthRepository =
require("../repositories/auth.repository");

const AuthValidator =
require("../validators/auth.validator");

const Password =
require("../utils/password");

const Jwt =
require("../utils/jwt");

class AuthService {

    /**
     * ======================================================
     * Login
     * ======================================================
     */
    async login(data, request) {

        // Validate Input
        const validation =

            AuthValidator.validateLogin(data);

        if (!validation.valid) {

            return {

                success: false,

                errors: validation.errors

            };

        }

        // Find User
        const user =

            await AuthRepository.findByUsername(

                data.username

            );

        if (!user) {

            await AuthRepository.saveLoginLog({

                user_id: null,

                ip_address: request.ip,

                user_agent:

                    request.headers["user-agent"],

                status: "failed"

            });

            return {

                success: false,

                message: "Invalid username or password."

            };

        }

        // User Status
        if (user.status !== "active") {

            return {

                success: false,

                message:

                    "Your account is inactive."

            };

        }

        // Verify Password
        const matched =

            await Password.compare(

                data.password,

                user.password

            );

        if (!matched) {

            await AuthRepository.saveLoginLog({

                user_id: user.id,

                ip_address: request.ip,

                user_agent:

                    request.headers["user-agent"],

                status: "failed"

            });

            return {

                success: false,

                message: "Invalid username or password."

            };

        }

        // Generate Token
        const token =

            Jwt.generate(user);

        // Update Last Login
        await AuthRepository.updateLastLogin(

            user.id

        );

        // Login Log
        await AuthRepository.saveLoginLog({

            user_id: user.id,

            ip_address: request.ip,

            user_agent:

                request.headers["user-agent"],

            status: "success"

        });

        // Remove Password
        delete user.password;

        return {

            success: true,

            token,

            user

        };

    }

    /**
     * ======================================================
     * Current User
     * ======================================================
     */
    async me(id) {

        const user =

            await AuthRepository.findById(id);

        if (!user) {

            return {

                success: false,

                message: "User not found."

            };

        }

        return {

            success: true,

            user

        };

    }

    /**
     * ======================================================
     * Change Password
     * ======================================================
     */
    async changePassword(userId, data) {

        // Validate
        const validation =

            AuthValidator

                .validateChangePassword(data);

        if (!validation.valid) {

            return {

                success: false,

                errors: validation.errors

            };

        }

        // Find User
        const user =

            await AuthRepository.findById(userId);

        if (!user) {

            return {

                success: false,

                message: "User not found."

            };

        }

        // Get Full User (contains password)
        const loginUser =

            await AuthRepository.findByUsername(

                user.username

            );

        // Verify Current Password
        const matched =

            await Password.compare(

                data.currentPassword,

                loginUser.password

            );

        if (!matched) {

            return {

                success: false,

                message:

                    "Current password is incorrect."

            };

        }

        // Hash New Password
        const hash =

            await Password.hash(

                data.newPassword

            );

        // Update
        await AuthRepository.updatePassword(

            userId,

            hash

        );

        return {

            success: true,

            message:

                "Password updated successfully."

        };

    }

}

module.exports =

new AuthService();