import CONSTANTS from "../config/constants";
import log from "../config/log";
import CustomRequest from "../types/requestType";
import { Response } from "express";
import { isUserPartner } from "../utils/isUserPartner";
import staffDB from "../models/staff.model";
import occupancyDB from "../models/occupancy.model";
import moment from "moment";

const discounts: any = {};

discounts.Add = async (req: CustomRequest, res: Response) => {
  const C = "Discount Controller";
  const F = "Add";

  try {
    const {
      discountType,
      discount,
      discountPeriod,
      isDiscountFromFirstMonth,
      tenantId,
    } = req.body;

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Discount Type [${discountType}], Discount [${discount}], Discount Period [${discountPeriod}], Discount Direction [${isDiscountFromFirstMonth}]`
    );

    const userType = req.userType;
    // let discountEndDate = null;
    // let discountStartDate = null;

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );

    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${
          isPartner ? `Partner Id [${req.id}]` : `Client Id [${clientId}]`
        }, ${isPartner ? "Partner Requesting" : "Client Requesting"}....`
      );
    } else {
      const staff = await staffDB.getById({
        id: req.id,
      });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      if (
        staff.role !== CONSTANTS.STAFF_ROLES.ADMIN &&
        staff.role !== CONSTANTS.STAFF_ROLES.WARDEN &&
        staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE &&
        staff.role !== CONSTANTS.STAFF_ROLES.SALES_HEAD &&
        staff.role !== CONSTANTS.STAFF_ROLES.SUPER_ADMIN
      ) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Only Admin or Warden Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }

      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Admin/Warden Requesting....`
      );
    }

    const occupancy = await occupancyDB.getByTenantId({
      tenantId: req.body.tenantId,
      clientId: clientId,
    });

    if (!occupancy) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Tenant Id [${req.body.tenantId}], No Occupancy Found`
      );
      return res.status(400).json({
        msg: CONSTANTS.MSG.INVALID_REQUEST,
        isSuccess: false,
      });
    }

    if (Number(occupancy.discountPeriod) > 0) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Tenant Id [${tenantId}], Discount Already Applied`
      );

      return res.status(400).json({
        msg: "Discount already applied",
        isSuccess: false,
      });
    }

    await occupancyDB.addDiscount({
      tenantId: tenantId,
      clientId: clientId,
      discountType,
      discount,
      discountPeriod,
      discountStartDate: null,
      discountEndDate: null,
      isDiscountFromFirstMonth,
    });

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Tenant Id [${tenantId}], Discount Type [${discountType}], Discount [${discount}], Discount Period [${discountPeriod}], Discount Added Successfully`
    );

    return res.status(200).json({
      msg: "Discount added successfully",
      isSuccess: true,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

discounts.Edit = async (req: CustomRequest, res: Response) => {
  const C = "Discount Controller";
  const F = "Edit";

  try {
    let {
      discountType,
      discount,
      discountPeriod,
      isDiscountFromFirstMonth,
      periodOperation,
      tenantId,
    } = req.body;

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Discount Type [${discountType}], Discount [${discount}], Discount Period [${discountPeriod}], Discount Period Operation [${periodOperation}], Discount Direction [${isDiscountFromFirstMonth}]`
    );

    const userType = req.userType;

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );

    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${
          isPartner ? `Partner Id [${req.id}]` : `Client Id [${clientId}]`
        }, ${isPartner ? "Partner Requesting" : "Client Requesting"}....`
      );
    } else {
      const staff = await staffDB.getById({
        id: req.id,
      });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      if (
        staff.role !== CONSTANTS.STAFF_ROLES.ADMIN &&
        staff.role !== CONSTANTS.STAFF_ROLES.WARDEN &&
        staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE
      ) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Only Admin or Warden Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }

      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Admin/Warden Requesting....`
      );
    }

    const occupancy = await occupancyDB.getByTenantId({
      tenantId: req.body.tenantId,
      clientId: clientId,
    });

    if (!occupancy) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Tenant Id [${req.body.tenantId}], No Occupancy Found`
      );
      return res.status(400).json({
        msg: CONSTANTS.MSG.INVALID_REQUEST,
        isSuccess: false,
      });
    }

    if (periodOperation === "sub") {
      let cyclesRemaining = moment().date(occupancy.rentalCycle).diff(occupancy.discountEndDate, "months");
      cyclesRemaining = cyclesRemaining / occupancy.rentalType;
      if (cyclesRemaining < discountPeriod) {
        return res.status(400).json({
          msg: `Only ${cyclesRemaining} cycles remaining. Can't reduce more than that.`,
          isSuccess: false,
        });
      }
      if (cyclesRemaining === discountPeriod) {
        discountType = 1;
        discount = 0;
        isDiscountFromFirstMonth = 1;
        discountPeriod = 0;
      }
    }

    await occupancyDB.addDiscount({
      tenantId: tenantId,
      clientId: clientId,
      discountType,
      discount,
      discountPeriod:
        periodOperation === "add"
          ? occupancy.discountPeriod + discountPeriod
          : occupancy.discountPeriod - discountPeriod,
      discountStartDate: periodOperation === "add" 
        ? moment(occupancy.discountStartDate).add((discountPeriod * occupancy.rentalType), "months").format("YYYY-MM-DD") 
        : moment(occupancy.discountStartDate).subtract((discountPeriod * occupancy.rentalType), "months").format("YYYY-MM-DD"),
      discountEndDate: periodOperation === "add" 
        ? moment(occupancy.discountEndDate).add((discountPeriod * occupancy.rentalType), "months").format("YYYY-MM-DD") 
        : moment(occupancy.discountEndDate).subtract((discountPeriod * occupancy.rentalType), "months").format("YYYY-MM-DD"),
      isDiscountFromFirstMonth,
    });

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Tenant Id [${tenantId}], Discount Type [${discountType}], Discount [${discount}], Discount Period [${discountPeriod}], Discount Edited Successfully`
    );

    return res.status(200).json({
      msg: "Discount edited successfully",
      isSuccess: true,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

discounts.Remove = async (req: CustomRequest, res: Response) => {
  const C = "Discount Controller";
  const F = "Remove";

  try {
    const { tenantId } = req.body;

    const userType = req.userType;
    let staff :any;
    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );

    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${
          isPartner ? `Partner Id [${req.id}]` : `Client Id [${clientId}], Tenant Id [${tenantId}]`
        }, ${isPartner ? "Partner Requesting" : "Client Requesting"}....`
      );
    } else {
      staff = await staffDB.getById({
        id: req.id,
      });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }
      clientId = staff.clientId;
      if (
        staff.role !== CONSTANTS.STAFF_ROLES.ADMIN &&
        staff.role !== CONSTANTS.STAFF_ROLES.WARDEN &&
        staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE
      ) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], Client Id [${clientId}], Staff Role [${staff.role}], Only Admin or Warden Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }

      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Admin/Warden Requesting....`
      );
    }

    await occupancyDB.addDiscount({
      tenantId: tenantId,
      clientId: clientId,
      discountType: 0,
      discount: 0,
      discountPeriod: 0,
      discountStartDate: null,
      discountEndDate: null,
      isDiscountFromFirstMonth: null,
    });
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(`[${C}], [${F}], ${
            isPartner ? `Partner Id [${req.id}]` : `Client Id [${clientId}], Tenant Id [${tenantId}]`
        }, Discount Removed Successfully`);
    } else {
      log.info(`[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Tenant Id [${tenantId}], Discount Removed Successfully`);
    }
    return res.status(200).json({
      msg: "Discount Removed Successfully",
      isSuccess: true,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
}

export default discounts;
