import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import * as bcrypt from 'bcrypt';
import { ModelService } from '../../model/model.service';
import { ConfigService } from '@nestjs/config';
import { CommonService } from '../../common/common.service';
import * as dto from './dto/index';
import * as path from "path";
import * as fs from "fs";
import { Types } from 'mongoose';


@Injectable()
export class StaffService {
    private admin_scope: string
    
    constructor(
        private readonly Model: ModelService,
        private readonly ConfigService: ConfigService,
        private readonly CommonService: CommonService
    ) {
        this.admin_scope = this.ConfigService.get<string>('ADMIN_SCOPE');

    }

    create_admin_staff = async (dto: dto.staff.admin_staff_create) => {
        try {
            const { email, country_code, name, phone_no, module_permission, profile_pic } = dto;

            const check_email = await this.Model.UserModel.findOne({ email: email.trim().toLowerCase(), is_deleted: false });
            if(check_email){
                throw new HttpException(
                    `User already exist with ${email}! Please try with another email.`,
                    HttpStatus.BAD_REQUEST
                )
            }

            const payload = {
                email: email.trim().toLowerCase(),
                country_code,
                phone_no,
                name,
                password: await bcrypt.hash(dto.password, 10),
                type: "STAFF",
                is_email_verified: true,
                is_phone_verified: true,
                module_permission,
                profile_pic
            }
            const staff = await this.Model.UserModel.create(payload);
            this.send_staff_invitation_email({ email: email, staff_name: name, password: dto.password, url: process.env.ADMIN_URL })
            return staff;            
        } catch (err) {
            throw err;
        }
    };

    async send_staff_invitation_email(data: any) {
        try {
          const  { email, staff_name, password, url } = data
          let file_path = path.resolve(__dirname, './assets/email_templates/staff_invitation.html');
          let html = fs.readFileSync(file_path, { encoding: 'utf-8' });
          html = html.replace('%staff_name%', staff_name);
          html = html.replace('%email%', email);
          html = html.replace('%password%', password);
          html = html.replace('%url%', url);
          html = html.replace('%web_url%', url);
          let subject = "Qixs Account Credentials"
    
          await this.CommonService.send_email(email, subject, html)
        } catch (error) {
          throw error
        }
    }

    update_admin_staff = async (dto: dto.staff.admin_staff_update, _id: string) => {
        try {
            const { country_code, name, phone_no, module_permission, profile_pic } = dto;

            const payload = {
                ...(country_code && { country_code: country_code }),
                ...(phone_no && { phone_no: phone_no }),
                ...(name && { name: name }),
                ...(profile_pic && { profile_pic: profile_pic }),
                ...(module_permission && { module_permission: module_permission }),
            }
            const staff = await this.Model.UserModel.findByIdAndUpdate(new Types.ObjectId(_id), payload, { new: true });
            return payload;            
        } catch (err) {
            throw err;
        }
    };

    delete_admin_staff = async (_id: string) => {
        try {
            const payload = {
                is_deleted: true,
            }
            const staff = await this.Model.UserModel.findByIdAndUpdate(new Types.ObjectId(_id), payload, { new: true });
            return payload;            
        } catch (err) {
            throw err;
        }
    };

    ger_admin_staff_details = async (_id: string) => {
        try {
            const staff = await this.Model.UserModel.findById(new Types.ObjectId(_id));
            return staff;            
        } catch (err) {
            throw err;
        }
    };

    async get_admin_staff(body: dto.staff.pagination_list) {
        try {
            const { pagination, limit, search } = body;
            const options = await this.CommonService.set_options(pagination, limit)
            const query = {
                type: "STAFF",
                is_deleted: false,
                ...(search && {
                $or: [
                    { name: { $regex: search, $options: "i" } },
                    { email: { $regex: search, $options: "i" } },
                    { phone_no: { $regex: search, $options: "i" } }]
                })
            }

            let data = await this.Model.UserModel.find(query, {}, options)
            let count = await this.Model.UserModel.countDocuments(query)

            return { 
                count, 
                data 
            }
        } catch (error) {
          throw error
        }
    }
}
