"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserController = void 0;
const common_1 = require("@nestjs/common");
const user_services_1 = require("../user/user.services");
const user_entity_1 = require("../user/user.entity");
const swagger_1 = require("@nestjs/swagger");
const create_user_dto_1 = require("./create-user.dto");
const UpdateUserDto_1 = require("./UpdateUserDto");
const auth_service_1 = require("../user/auth/auth.service");
const LoginDto_1 = require("../user/auth/LoginDto");
const JwtAuthGuard_1 = require("../user/auth/JwtAuthGuard");
const GenerateOtpDto_1 = require("./GenerateOtpDto");
const ValidateOtpDto_1 = require("./ValidateOtpDto");
const jwt_1 = require("@nestjs/jwt");
const roles_decorator_1 = require("./auth/roles.decorator");
const roles_guard_1 = require("./auth/roles.guard");
const user_entity_2 = require("./user.entity");
const sms_service_1 = require("../smsgetway/sms.service");
const otp_email_service_1 = require("../emailotp/otp-email.service");
const ChangePasswordDto_1 = require("./ChangePasswordDto");
const ForgotPasswordDto_1 = require("./ForgotPasswordDto");
const ResetPasswordDto_1 = require("./ResetPasswordDto");
const UpdateUserDeviceIdDto_1 = require("./UpdateUserDeviceIdDto");
let UserController = class UserController {
    constructor(jwtService, userService, authService, smsService, emailOtpService) {
        this.jwtService = jwtService;
        this.userService = userService;
        this.authService = authService;
        this.smsService = smsService;
        this.emailOtpService = emailOtpService;
    }
    findAll() {
        return this.userService.findAll();
    }
    async register(createUserDto) {
        try {
            const user = await this.userService.registerUser(createUserDto);
            const bypassUsers = (process.env.OTP_BYPASS_USERS ?? '').split(',').map(e => e.trim());
            const isBypass = bypassUsers.includes(user.email);
            const otp = isBypass ? '123456' : Math.floor(100000 + Math.random() * 900000).toString();
            user.otp = otp;
            user.otpExpiresAt = new Date(Date.now() + 15 * 60 * 1000);
            user.otpStatus = false;
            if (!isBypass)
                await this.smsService.sendOtp(createUserDto.mobileNumber, otp, createUserDto.hash);
            await this.userService.updateOtpUser(user);
            return {
                message: 'User registered successfully. OTP sent.',
                data: {
                    user,
                    otp,
                },
            };
        }
        catch (error) {
            throw new common_1.BadRequestException(error.message);
        }
    }
    async generateOTP(generateOtpDto) {
        try {
            const user = await this.userService.findUserByMobile(generateOtpDto.emailmobile);
            if (!user) {
                throw new common_1.BadRequestException('User not found with the provided mobile number.');
            }
            const bypassUsers = (process.env.OTP_BYPASS_USERS ?? '').split(',').map(e => e.trim());
            const isBypass = bypassUsers.includes(user.email);
            const otp = isBypass ? '123456' : Math.floor(100000 + Math.random() * 900000).toString();
            user.otp = otp;
            user.otpExpiresAt = new Date(Date.now() + 15 * 60 * 1000);
            user.otpStatus = false;
            const isEmails = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(generateOtpDto.emailmobile);
            if (!isBypass) {
                if (!isEmails) {
                    await this.smsService.sendOtp(user.mobileNumber, otp, generateOtpDto.hash);
                }
                else {
                    await this.emailOtpService.sendOtp(user.email, otp);
                }
            }
            await this.userService.updateOtpUser(user);
            return {
                message: 'OTP generated and sent successfully.',
                data: {
                    emailmobile: isEmails ? user.email : user.mobileNumber,
                    otp,
                },
            };
        }
        catch (error) {
            throw new common_1.BadRequestException(error.message);
        }
    }
    async login(loginDto) {
        const { emailmobile, credential, type } = loginDto;
        let identifier = emailmobile;
        const isEmails = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(identifier);
        if (!identifier) {
            throw new common_1.UnauthorizedException('Email or mobile number is required');
        }
        try {
            const user = await this.authService.validateUser(identifier, credential);
            if (type) {
                if (type == "driver" && !user.roles.includes(user_entity_2.UserRole.DRIVER)) {
                    throw new common_1.UnauthorizedException(`User does not have role: ${type}`);
                }
            }
            const bypassUsers = (process.env.OTP_BYPASS_USERS ?? '').split(',').map(e => e.trim());
            const isBypass = bypassUsers.includes(user.email);
            const otp = isBypass ? '123456' : Math.floor(100000 + Math.random() * 900000).toString();
            user.otp = otp;
            user.otpExpiresAt = new Date(Date.now() + 15 * 60 * 1000);
            user.otpStatus = false;
            await this.userService.updateOtpUser(user);
            if (!isBypass) {
                if (!isEmails) {
                    await this.smsService.sendOtp(user.mobileNumber, otp, loginDto.hash);
                }
                else {
                    await this.emailOtpService.sendOtp(user.email, otp);
                }
            }
            user.deviceId = loginDto.deviceId;
            user.deviceType = loginDto.deviceType;
            await this.userService.updateDeviceIdUser(user);
            return this.authService.login(user);
        }
        catch (error) {
            throw new common_1.UnauthorizedException(error.message || 'Invalid credentials');
        }
    }
    async firebaseLogin(body) {
        return this.authService.socialLoginWithFirebase(body?.idToken);
    }
    async getProfile(userId) {
        try {
            const user = await this.userService.findById(userId);
            if (!user) {
                throw new common_1.NotFoundException('User not found');
            }
            return user;
        }
        catch (error) {
            if (error instanceof common_1.NotFoundException)
                throw error;
            throw new common_1.InternalServerErrorException('Failed to fetch user profile');
        }
    }
    async updateUser(userId, updateUserDataDto) {
        const updatedUser = await this.userService.updateUser(userId, updateUserDataDto);
        if (!updatedUser) {
            throw new common_1.NotFoundException(`User with userId ${userId} not found`);
        }
        return updatedUser;
    }
    async validateOtp(body) {
        const { identifier, otp } = body;
        const isValid = await this.userService.validateOtp(identifier, otp);
        if (isValid) {
            const user = await this.userService.findOneMobileEmail(identifier);
            if (user) {
                await this.userService.updateOtpUserStatus(user);
                return {
                    status: true,
                    message: 'OTP validated successfully',
                    userdata: user,
                };
            }
            else {
                return { status: false, message: 'User not found' };
            }
        }
    }
    addRole(id, role) {
        return this.userService.addRole(id, role);
    }
    removeRole(id, role) {
        return this.userService.removeRole(id, role);
    }
    async updateStatus(id, updateStatusDto) {
        try {
            const updated = await this.userService.updateStatus(+id, updateStatusDto.status);
            return {
                status: true,
                message: "User status successfully updated.",
                data: updated,
            };
        }
        catch (error) {
            throw new common_1.BadRequestException(error.message);
        }
    }
    async updateDeviceId(id, updateuserDeviceIdDto) {
        try {
            const updated = await this.userService.updateDeviceIdNotification(+id, updateuserDeviceIdDto.deviceId, updateuserDeviceIdDto.deviceType);
            return {
                status: true,
                message: "User successfully updated.",
                data: updated,
            };
        }
        catch (error) {
            throw new common_1.BadRequestException(error.message);
        }
    }
    async changePassword(id, changePasswordDto) {
        try {
            const updated = await this.userService.changePassword(+id, changePasswordDto.password);
            return {
                status: true,
                message: "User password changed successfully.",
                data: updated,
            };
        }
        catch (error) {
            throw new common_1.BadRequestException(error.message);
        }
    }
    async forgotPassword(dto) {
        return this.authService.forgotPassword(dto.identifier);
    }
    async resetPassword(req, dto) {
        const userId = req.user.userId;
        return this.userService.changePassword(userId, dto.password);
    }
};
exports.UserController = UserController;
__decorate([
    (0, common_1.UseGuards)(JwtAuthGuard_1.JwtAuthGuard, roles_guard_1.RolesGuard),
    (0, common_1.Get)('alluser'),
    (0, swagger_1.ApiResponse)({ status: 201, description: 'Users fetched successfully.', type: [user_entity_1.User] }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", void 0)
], UserController.prototype, "findAll", null);
__decorate([
    (0, common_1.Post)('register'),
    (0, swagger_1.ApiOperation)({ summary: 'Register a new user' }),
    (0, swagger_1.ApiResponse)({ status: 201, description: 'User registered successfully.', type: user_entity_1.User }),
    (0, swagger_1.ApiBadRequestResponse)({ description: 'Invalid data provided' }),
    __param(0, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [create_user_dto_1.CreateUserDto]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "register", null);
__decorate([
    (0, common_1.Post)('generateOtp'),
    (0, swagger_1.ApiOperation)({ summary: 'Generate an OTP for the user using mobile number' }),
    (0, swagger_1.ApiResponse)({ status: 201, description: 'OTP generated and sent successfully.' }),
    (0, swagger_1.ApiBadRequestResponse)({ description: 'Invalid mobile number or user not found' }),
    __param(0, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [GenerateOtpDto_1.GenerateOtpDto]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "generateOTP", null);
__decorate([
    (0, common_1.Post)('login'),
    (0, swagger_1.ApiOperation)({ summary: 'Login to the system' }),
    (0, swagger_1.ApiResponse)({ status: 200, description: 'Login successful', type: user_entity_1.User }),
    (0, swagger_1.ApiResponse)({ status: 401, description: 'Unauthorized' }),
    __param(0, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [LoginDto_1.LoginDto]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "login", null);
__decorate([
    (0, common_1.Post)('firebase-login'),
    (0, swagger_1.ApiOperation)({ summary: 'Social login (Google/Apple) via a Firebase ID token' }),
    (0, swagger_1.ApiResponse)({ status: 200, description: 'Social login successful', type: user_entity_1.User }),
    (0, swagger_1.ApiResponse)({ status: 401, description: 'Invalid Firebase token' }),
    __param(0, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "firebaseLogin", null);
__decorate([
    (0, common_1.Get)(':userId'),
    (0, swagger_1.ApiOperation)({ summary: 'Get user profile by userId' }),
    (0, swagger_1.ApiResponse)({
        status: 200,
        description: 'Profile fetched successfully',
        type: user_entity_1.User,
    }),
    (0, swagger_1.ApiBadRequestResponse)({ description: 'Bad Request, invalid data provided' }),
    (0, swagger_1.ApiNotFoundResponse)({ description: 'User not found' }),
    __param(0, (0, common_1.Param)('userId', common_1.ParseIntPipe)),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Number]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "getProfile", null);
__decorate([
    (0, common_1.Put)(':userId'),
    (0, swagger_1.ApiOperation)({ summary: 'Update a user by userId' }),
    (0, swagger_1.ApiResponse)({
        status: 200,
        description: 'User updated successfully',
        type: user_entity_1.User,
    }),
    (0, swagger_1.ApiBadRequestResponse)({ description: 'Bad Request, invalid data provided' }),
    (0, swagger_1.ApiNotFoundResponse)({ description: 'User not found' }),
    (0, swagger_1.ApiBody)({
        description: 'User data to be updated',
        type: UpdateUserDto_1.UpdateUserDto,
    }),
    __param(0, (0, common_1.Param)('userId')),
    __param(1, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, UpdateUserDto_1.UpdateUserDto]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "updateUser", null);
__decorate([
    (0, common_1.Post)('validateotp'),
    (0, swagger_1.ApiOperation)({ summary: 'Validate OTP for user login or verification' }),
    (0, swagger_1.ApiBody)({
        description: 'Input identifier (email or mobile) and OTP for validation',
        type: ValidateOtpDto_1.ValidateOtpDto,
    }),
    (0, swagger_1.ApiResponse)({ status: 200 }),
    __param(0, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ValidateOtpDto_1.ValidateOtpDto]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "validateOtp", null);
__decorate([
    (0, common_1.Patch)(':id/add-role/:role'),
    (0, roles_decorator_1.Roles)(user_entity_2.UserRole.ADMIN),
    __param(0, (0, common_1.Param)('id')),
    __param(1, (0, common_1.Param)('role')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Number, String]),
    __metadata("design:returntype", void 0)
], UserController.prototype, "addRole", null);
__decorate([
    (0, common_1.Patch)(':id/remove-role/:role'),
    (0, roles_decorator_1.Roles)(user_entity_2.UserRole.ADMIN),
    __param(0, (0, common_1.Param)('id')),
    __param(1, (0, common_1.Param)('role')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Number, String]),
    __metadata("design:returntype", void 0)
], UserController.prototype, "removeRole", null);
__decorate([
    (0, common_1.Patch)(":id/status"),
    __param(0, (0, common_1.Param)("id")),
    __param(1, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, UpdateUserDto_1.UpdateStatusDto]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "updateStatus", null);
__decorate([
    (0, common_1.Patch)(":id/updatedeviceid"),
    __param(0, (0, common_1.Param)("id")),
    __param(1, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, UpdateUserDeviceIdDto_1.UpdateUserDeviceIdDto]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "updateDeviceId", null);
__decorate([
    (0, common_1.Patch)("changepassword/:id"),
    __param(0, (0, common_1.Param)("id")),
    __param(1, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, ChangePasswordDto_1.ChangePasswordDto]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "changePassword", null);
__decorate([
    (0, common_1.Post)('forgot-password'),
    (0, swagger_1.ApiOperation)({ summary: 'Send password reset link to email or mobile' }),
    __param(0, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ForgotPasswordDto_1.ForgotPasswordDto]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "forgotPassword", null);
__decorate([
    (0, common_1.UseGuards)(JwtAuthGuard_1.JwtAuthGuard, roles_guard_1.RolesGuard),
    (0, common_1.Patch)('reset-password'),
    (0, swagger_1.ApiOperation)({ summary: 'Reset password using reset token' }),
    __param(0, (0, common_1.Req)()),
    __param(1, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, ResetPasswordDto_1.ResetPasswordDto]),
    __metadata("design:returntype", Promise)
], UserController.prototype, "resetPassword", null);
exports.UserController = UserController = __decorate([
    (0, swagger_1.ApiTags)('users'),
    (0, common_1.Controller)('users'),
    __metadata("design:paramtypes", [jwt_1.JwtService,
        user_services_1.UserService,
        auth_service_1.AuthService,
        sms_service_1.SmsService,
        otp_email_service_1.emailOtpService])
], UserController);
//# sourceMappingURL=user.controller.js.map