"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);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OwnerService = void 0;
const common_1 = require("@nestjs/common");
const jwt_1 = require("@nestjs/jwt");
const config_1 = require("../../config");
const app_string_1 = require("../../constant/app-string");
const utils_1 = require("../../utils");
const access_control_service_1 = require("../access-control/access-control.service");
const configurations_service_1 = require("../configurations/configurations.service");
const owner_dto_1 = require("./owner.dto");
let OwnerService = class OwnerService {
    constructor(db, configuration, hashService, jwt, mailService, uploadService, accessControlService) {
        this.db = db;
        this.configuration = configuration;
        this.hashService = hashService;
        this.jwt = jwt;
        this.mailService = mailService;
        this.uploadService = uploadService;
        this.accessControlService = accessControlService;
    }
    async createOwner(data) {
        try {
            const existingOwner = await this.db.owner.findFirst({
                where: {
                    OR: [{ email: data.email }, { username: data.username }],
                },
            });
            if (existingOwner) {
                throw (0, utils_1.createFieldError)('root', 'An owner already exists. Multiple owners are not allowed.', common_1.HttpStatus.BAD_REQUEST);
            }
            const hashedPassword = await this.hashService.hashPassword(data.password);
            const otp = (0, utils_1.getOtp)();
            const { profile } = (0, config_1.envConfig)().server;
            if (!data.email) {
                throw (0, utils_1.createFieldError)('email', 'Email is required');
            }
            const owner = await this.db.owner.upsert({
                where: {
                    email: data.email,
                },
                create: {
                    name: data.name,
                    username: data.username,
                    email: data.email,
                    password: hashedPassword,
                    otp,
                    status: config_1.Status.unverified,
                    image: {
                        file_name: profile,
                        original_name: 'profile.webp',
                        file_size: 8192,
                        mime_type: 'image/webp',
                    },
                },
                update: {
                    otp,
                    status: config_1.Status.unverified,
                },
            });
            const { data: parsedOwner } = owner_dto_1.authResponseSchema.safeParse(owner);
            this.mailService.sendMail('otp-mail', data.email, {
                name: data?.name,
                otp,
            }, 'Welcome to Team Tracker');
            return {
                data: parsedOwner,
                message: app_string_1.AppString.CONFIRMATION_OTP_SENT,
            };
        }
        catch (error) {
            config_1.logger.error(`Error in resendOtp: ${String(error)}`);
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async resendOtp(email) {
        try {
            const owner = await this.db.owner.findFirst({
                where: {
                    email,
                    status: config_1.Status.unverified,
                },
            });
            if (!owner) {
                throw (0, utils_1.createFieldError)('email', app_string_1.AppString.OWNER_NOT_FOUND_EMAIL, 404);
            }
            const otp = (0, utils_1.getOtp)();
            await this.db.owner.update({
                where: {
                    email,
                },
                data: {
                    otp,
                },
            });
            this.mailService.sendMail('otp-mail', email, { name: owner?.name, otp }, 'Resend OTP for Team Tracker');
            return {
                message: app_string_1.AppString.CONFIRMATION_OTP_SENT,
                data: email,
                status: common_1.HttpStatus.OK,
                details: null,
            };
        }
        catch (error) {
            config_1.logger.error(`Error in resendOtp: ${String(error)}`);
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async verifyOtp(email, otp) {
        try {
            const owner = await this.db.owner.findFirst({
                where: { email, status: config_1.Status.unverified },
            });
            if (!owner) {
                throw (0, utils_1.createFieldError)('email', app_string_1.AppString.OWNER_NOT_FOUND_EMAIL, 404);
            }
            const OTP_TTL_MS = 2 * 60 * 1000;
            if (owner.updated_at < new Date(Date.now() - OTP_TTL_MS)) {
                throw (0, utils_1.createFieldError)('otp', app_string_1.AppString.INVALID_EXPIRED_OTP);
            }
            if (owner.otp !== otp) {
                throw (0, utils_1.createFieldError)('otp', 'Invalid OTP');
            }
            const [updatedOwner, token] = await Promise.all([
                this.db.owner.update({
                    where: { email },
                    data: { status: config_1.Status.active, otp: null },
                }),
                this.configuration.createDefaultConfiguration(owner.id),
                this.accessControlService.ensureDefaultRoles(owner.id),
            ]).then(async ([updated]) => {
                const accessRoleId = await this.accessControlService.resolveAccessRoleIdBySlug(owner.id, updated.role ?? 'owner');
                const jwtToken = await this.jwt.signAsync({
                    sub: owner.id,
                    owner_id: owner.id,
                    email: owner.email,
                    role: updated.role,
                    access_role_id: accessRoleId,
                }, { expiresIn: '7d' });
                return [updated, jwtToken];
            });
            const { data: parsedOwner } = owner_dto_1.authResponseSchema.safeParse({
                ...updatedOwner,
                access_token: token,
            });
            return {
                data: parsedOwner,
                message: 'OTP verified successfully',
                status: common_1.HttpStatus.OK,
                details: null,
            };
        }
        catch (error) {
            if (error instanceof config_1.ErrorResponse)
                throw error;
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async signin(data) {
        try {
            const orConditions = [];
            const cleanEmail = data?.email?.trim()?.toLowerCase();
            const cleanUsername = data?.username?.trim();
            if (cleanEmail) {
                orConditions.push({ email: cleanEmail, status: config_1.Status.active });
            }
            if (cleanUsername) {
                orConditions.push({
                    username: cleanUsername,
                    status: config_1.Status.active,
                });
            }
            if (orConditions.length === 0) {
                config_1.logger.error('owner not found1 ' + orConditions);
                throw (0, utils_1.createGeneralError)(app_string_1.AppString.INVALID_CREDENTIALS, 'root', common_1.HttpStatus.EXPECTATION_FAILED);
            }
            const owner = await this.db.owner.findFirst({
                where: {
                    OR: orConditions,
                },
            });
            if (!owner) {
                config_1.logger.error(app_string_1.AppString.INVALID_CREDENTIALS);
                throw (0, utils_1.createGeneralError)(app_string_1.AppString.INVALID_CREDENTIALS, 'root', common_1.HttpStatus.EXPECTATION_FAILED);
            }
            const isPasswordValid = await this.hashService.comparePasswords(data?.password, owner.password);
            if (!isPasswordValid) {
                config_1.logger.error('owner not found2 ' + isPasswordValid);
                throw (0, utils_1.createGeneralError)(app_string_1.AppString.INVALID_CREDENTIALS, 'root', common_1.HttpStatus.EXPECTATION_FAILED);
            }
            config_1.logger.error(`Signin attempt isPasswordValid: ${isPasswordValid}`);
            await this.accessControlService.ensureDefaultRoles(owner.id);
            const accessRoleId = await this.accessControlService.resolveAccessRoleIdBySlug(owner.id, owner.role ?? 'owner');
            const token = await this.jwt.signAsync({
                sub: owner.id,
                owner_id: owner.id,
                email: owner.email,
                role: owner?.role,
                access_role_id: accessRoleId,
            }, { expiresIn: '7d' });
            const { data: parsedOwner } = owner_dto_1.authResponseSchema.safeParse({
                ...owner,
                access_token: token,
            });
            return {
                data: parsedOwner,
                message: app_string_1.AppString.SIGNIN_SUCCESSFULL,
            };
        }
        catch (error) {
            config_1.logger.error('owner not found3 ' + error);
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async updateOwner(data, id) {
        try {
            config_1.logger.info(`Received update request for owner ID: ${id} with data: ${JSON.stringify(data)}`);
            const owner = await this.db.owner.findFirst({
                where: {
                    id: id,
                    status: config_1.Status.active,
                },
            });
            if (!owner) {
                throw (0, utils_1.createFieldError)('id', app_string_1.AppString.OWNER_NOT_FOUND, 404);
            }
            let image = data?.image;
            if (image) {
                image = await this.uploadService.moveImage(image, 'owners');
            }
            const updatedOwner = await this.db.owner.update({
                where: {
                    id,
                },
                data: {
                    ...data,
                    image: image ?? owner.image,
                },
            });
            const { data: parsedOwner } = owner_dto_1.ownerResponseSchema.safeParse(updatedOwner);
            return {
                data: parsedOwner,
                message: app_string_1.AppString.OWNER_UPDATED_SUCCESSFULLY,
            };
        }
        catch (error) {
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async forgotPassword(email) {
        try {
            const owner = await this.db.owner.findFirst({
                where: {
                    email,
                    status: config_1.Status.active,
                },
            });
            if (!owner) {
                throw (0, utils_1.createFieldError)('email', app_string_1.AppString.OWNER_NOT_FOUND_EMAIL, 404);
            }
            const otp = (0, utils_1.getOtp)();
            await this.db.owner.update({
                where: {
                    email,
                },
                data: {
                    otp,
                },
            });
            this.mailService.sendMail('otp-mail', email, { name: owner?.name, otp }, 'Reset Password OTP for Team Tracker');
            return {
                message: app_string_1.AppString.PASSWORD_RESET_OTP_SENT,
                data: email,
                status: common_1.HttpStatus.OK,
                details: null,
            };
        }
        catch (error) {
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async resetVerifyOtp(data) {
        try {
            const owner = await this.db.owner.findFirst({
                where: {
                    email: data?.email,
                    status: config_1.Status.active,
                },
            });
            if (!owner) {
                throw (0, utils_1.createFieldError)('email', app_string_1.AppString.OWNER_NOT_FOUND_EMAIL, 404);
            }
            if (owner.updated_at < new Date(Date.now() - 2 * 60 * 1000)) {
                throw (0, utils_1.createFieldError)('otp', app_string_1.AppString.INVALID_EXPIRED_OTP);
            }
            if (owner?.otp !== data?.otp) {
                throw (0, utils_1.createFieldError)('otp', 'Invalid OTP');
            }
            return { message: 'OTP verify successfully' };
        }
        catch (error) {
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async resetPassword(data) {
        try {
            const owner = await this.db.owner.findFirst({
                where: {
                    email: data?.email,
                    status: config_1.Status.active,
                },
            });
            if (!owner) {
                throw (0, utils_1.createFieldError)('email', app_string_1.AppString.OWNER_NOT_FOUND_EMAIL, 404);
            }
            const hashedPassword = await this.hashService.hashPassword(data?.password);
            config_1.logger.error(`Signin attempt isPasswordValid: ${hashedPassword}`);
            await this.db.owner.update({
                where: {
                    email: data?.email,
                },
                data: {
                    password: hashedPassword,
                    otp: null,
                },
            });
            return { message: 'Password reset successfully' };
        }
        catch (error) {
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async changePassword(ownerId, data) {
        try {
            const owner = await this.db.owner.findFirst({
                where: {
                    id: ownerId,
                    status: config_1.Status.active,
                },
            });
            if (!owner) {
                throw (0, utils_1.createFieldError)('ownerId', app_string_1.AppString.OWNER_NOT_FOUND, 404);
            }
            const isPasswordValid = await this.hashService.comparePasswords(data?.current_password, owner.password);
            if (!isPasswordValid) {
                throw (0, utils_1.createFieldError)('currentPassword', app_string_1.AppString.INVALID_CREDENTIALS, common_1.HttpStatus.EXPECTATION_FAILED);
            }
            const hashedPassword = await this.hashService.hashPassword(data?.new_password);
            await this.db.owner.update({
                where: {
                    id: ownerId,
                },
                data: {
                    password: hashedPassword,
                },
            });
            return {
                message: app_string_1.AppString.PASSWORD_CHANGE_SUCCESSFULL,
                data: null,
                status: common_1.HttpStatus.OK,
                details: null,
            };
        }
        catch (error) {
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
};
exports.OwnerService = OwnerService;
exports.OwnerService = OwnerService = __decorate([
    (0, common_1.Injectable)(),
    __metadata("design:paramtypes", [config_1.DatabaseService,
        configurations_service_1.ConfigurationsService,
        config_1.HashService,
        jwt_1.JwtService,
        config_1.MailService,
        config_1.UploadService,
        access_control_service_1.AccessControlService])
], OwnerService);
//# sourceMappingURL=owner.service.js.map