import {
  HttpException,
  HttpStatus,
  Injectable,
  UnauthorizedException,
} from '@nestjs/common';
// import { ModelService } from 'src/model/model.service';

import { ConfigService } from '@nestjs/config';
import * as dto from './dto/index';
// import { ModelService } from 'src/model/model.service';
// import * as Error from '../handler/error.exception'
import * as bcrypt from 'bcrypt';
// import { CommonService } from 'src/common/common.service';
import { types } from 'util';
import { Types } from 'mongoose';
import * as random_string from 'randomstring';
import { count, log } from 'console';
import { Commission, contact_us_status_edit, payout_type } from './dto/admin';
import { ModelService } from '../model/model.service';
import { CommonService } from '../common/common.service';

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

  login = async (dto: dto.adminLogin) => {
    try {
      let { email, password } = dto;
      // ! check email exists
      let admin = await this.Model.UserModel.find({ email: email });
      if (admin.length) {
        // console.log("inside.......length");
        return await this.login_exisitng_admin(admin[0], dto);
      } else {
        // console.log("inside.......else");
        return await this.create_new_admin(dto);
      }
    } catch (err) {
      throw err;
    }
  };

  admin_profile = async (request: dto.adminData) => {
    try {
      // console.log("admin_data.....", request.user_data);
      let { _id } = request.user_data;
      let query = { _id: new Types.ObjectId(_id) };
      let options = { lean: true };
      let response = await this.Model.UserModel.findOne(
        query,
        { _v: 0 },
        options
      );
      // console.log("respodne.....", response);
      return response;
    } catch (err) {
      throw err;
    }
  };

  edit_profile = async (query_data: any, request: dto.adminData) => {
    try {
      let { name, profile_pic } = query_data;
      let { _id } = request.user_data;
      let query = { _id: new Types.ObjectId(_id) };

      let data_to_update: any = { updated_at: +new Date() };

      // Update name if provided
      if (name !== undefined) {
        data_to_update.name = name;
      }
      // Update profile_pic if provided, including explicitly setting it to null
      if (profile_pic !== undefined) {
        data_to_update.profile_pic = profile_pic;
      }

      let options = { new: true };
      let response = await this.Model.UserModel.findOneAndUpdate(
        query,
        data_to_update,
        options
      );

      return response;
    } catch (err) {
      throw err;
    }
  };

  async changePassword(body: dto.adminChangePass, request: dto.adminData) {
    try {
      let { oldPassword, newPassword } = body;
      let { _id: admin_id } = request.user_data;
      let query = { _id: admin_id };
      let projection = { __v: 0 };
      let options = { lean: true };
      let admin = await this.Model.UserModel.find(query, projection, options);
      // console.log(admin);
      if (admin.length) {
        let { _id, password } = admin[0];
        let decrypt = await bcrypt.compare(oldPassword, password);
        // console.log("password compare....", decrypt);

        if (decrypt != true) {
          throw new HttpException(
            'The current password you entered is incorrect. Please try again.',
            HttpStatus.BAD_REQUEST
          );
        } else {
          let pass_repeat = await bcrypt.compare(newPassword, password);
          // console.log("pass_repeat----->", pass_repeat)
          // console.log("pass_repeat------>1")
          if (pass_repeat) {
            // console.log("pass_repeat------>2")
            throw new HttpException(
              "Your new password matches your old password. To ensure your account's security, please choose a new and unique password.",
              HttpStatus.BAD_REQUEST
            );
          } else {
            let bycryt_password = await bcrypt.hash(newPassword, 10);
            let query = { _id: _id };
            let update = { password: bycryt_password };
            let options = {
              projection: {
                super_admin: 0,
                is_blocked: 0,
                is_deleted: 0,
                password: 0,
                __v: 0,
              },
              new: true,
            };
            let response = await this.Model.UserModel.findOneAndUpdate(
              query,
              update,
              options
            );
            return response;
          }
        }
      } else {
        throw new UnauthorizedException();
      }
    } catch (err) {
      throw err;
    }
  }

  login_exisitng_admin = async (admin: any, body: dto.adminLogin) => {
    try {
      let { _id, password: hash } = admin;
      let { password } = body;
      // console.log(hash, password);

      let decode = await bcrypt.compare(password, hash);
      // console.log(`🚀 ~ file: admin.service.ts:23 ~ AdminService ~ login ~ decode:`, decode)
      if (decode != true) {
        throw new HttpException('Wrong password', HttpStatus.BAD_REQUEST);
      } else {
        // ! update admin
        let query = { _id: _id };
        let update = { updated_at: +new Date() };
        let options = {
          projection: {
            full_name: 1,
            profile_pic: 1,
            email: 1,
            super_admin: 1,
            roles: 1,
            updated_at: 1,
            created_at: 1,
          },
          new: true,
          lean: true,
        };
        let update_admin = await this.Model.UserModel.findOneAndUpdate(
          query,
          update,
          options
        );
        let token_payload = {
          _id: _id,
          scope: this.admin_scope,
          token_gen_at: +new Date(),
        };
        let token = await this.CommonService.generate_token(token_payload);
        let save_session = await this.CommonService.create_admin_session(
          body,
          token_payload,
          token
        );
        update_admin['access_token'] = token;
        // update_admin.message = "Logged in"
        return update_admin;
      }
    } catch (err) {
      throw err;
    }
  };

  create_new_admin = async (body: dto.adminLogin) => {
    try {
      let { email, password } = body;
      if (email.toLowerCase() != 'admin@gmail.com') {
        throw new HttpException(`Please enter valid Email Address`, HttpStatus.BAD_REQUEST);
      }
      let hash = await bcrypt.hash('qwerty', 10);
      let data_to_save = {
        // type: "ADMIN",
        name: 'super admin',
        email: 'admin@gmail.com',
        profile_pic: null,
        password: hash,
        super_admin: true,
        created_at: +new Date(),
      };
      let create = await this.Model.UserModel.create(data_to_save);

      let query = { _id: create._id };
      let projection = {
        email: true,
        name: true,
        super_admin: true,
        roles: true,
        profile_pic: true,
        updated_at: true,
        created_at: true,
      };
      let options = { lean: true };
      let find = await this.Model.UserModel.findOne(query, projection, options);
      let token_payload = {
        _id: find._id,
        scope: this.admin_scope,
        token_gen_at: +new Date(),
      };
      let token = await this.CommonService.generate_token(token_payload);
      let save_session = await this.CommonService.create_admin_session(
        body,
        token_payload,
        token
      );
      find['access_token'] = token;
      return find;
    } catch (err) {
      throw err;
    }
  };

  // create_driver = async (body: dto.driver_signup) => {
  //     try {
  //         let {email}=body
  //         let existingDriver = await this.Model.UserModel.findOne({ email: email },{__v:0},{lean:true});
  //         if (existingDriver) {
  //             throw new HttpException('Email already exists',HttpStatus.BAD_REQUEST);
  //         }
  //         let pass: any = await this.generate_product_id();
  //         console.log("genertepass----------->", pass);
  //         let encrypt_pass = await this.CommonService.encriptPass(pass.toString());
  //         console.log("encrypt_pass", encrypt_pass);
  //         let payload: any = {
  //             email,
  //             pass
  //         };
  //         await this.EmailService.send_welcome_email_driver(payload);
  //         let data_to_save = {
  //             type:"DRIVER",
  //             email: email.toLowerCase(),
  //             password: encrypt_pass,
  //             is_email_verified:true
  //         };
  //         let driver = await this.Model.UserModel.create(data_to_save);
  //         console.log("driver---------------->",driver);

  //         return driver;
  //     } catch (error) {
  //         throw error;
  //     }
  // };

  async generate_product_id() {
    try {
      let static_value = 'ORDER';
      let options = {
        length: 6,
        charset: 'alphanumeric',
        capitalization: 'uppercase',
      };
      let random_value = random_string.generate(options);

      return random_value;
    } catch (error) {
      throw error;
    }
  }
}
