import DatabaseConfig from "../DatabaseConfig";
import BearerTokenAuthorization from "../Middleware/BearerTokenAuthorization";
import BillingService from "../Services/BillingService";
import ProjectService from "../Services/ProjectService";
import PromoCodeService from "../Services/PromoCodeService";
import ResellerPlanService from "../Services/ResellerPlanService";
import Response from "../Utils/Response";
import BaseAPI from "./BaseAPI";
import StatusCode from "../../Types/API/StatusCode";
import URL from "../../Types/API/URL";
import Email from "../../Types/Email";
import BadDataException from "../../Types/Exception/BadDataException";
import PromoCode from "../../Models/DatabaseModels/PromoCode";
import ResellerPlan from "../../Models/DatabaseModels/ResellerPlan";
export default class ResellerPlanAPI extends BaseAPI {
    constructor() {
        var _a;
        super(ResellerPlan, ResellerPlanService);
        /*
         * Reseller Plan Action API
         * TODO: Refactor this API and make it partner specific.
         */
        this.router.post(`${(_a = new this.entityType()
            .getCrudApiPath()) === null || _a === void 0 ? void 0 : _a.toString()}/action/:resellerId`, BearerTokenAuthorization.isAuthorizedBearerToken, async (req, res, next) => {
            var _a, _b, _c, _d, _e;
            try {
                const resellerId = req.params["resellerId"];
                if (!resellerId) {
                    throw new Error("Invalid reseller id.");
                }
                if (resellerId.trim().toLowerCase() !==
                    ((_b = (_a = req.bearerTokenData) === null || _a === void 0 ? void 0 : _a.resellerId) === null || _b === void 0 ? void 0 : _b.trim().toLowerCase())) {
                    throw new Error("Invalid reseller id found in access token");
                }
                const action = req.body.action;
                if (!action) {
                    throw new BadDataException("Invalid action.");
                }
                const resellerPlanId = req.body.plan_id;
                if (!resellerPlanId) {
                    throw new BadDataException("Invalid reseller plan id.");
                }
                // check reseller Plan.
                const resellerPlan = await ResellerPlanService.findOneBy({
                    query: {
                        planId: resellerPlanId,
                    },
                    select: {
                        _id: true,
                        planId: true,
                        reseller: {
                            resellerId: true,
                        },
                        teamMemberLimit: true,
                        monitorLimit: true,
                        planType: true,
                    },
                    props: {
                        isRoot: true,
                    },
                });
                if (!resellerPlan) {
                    throw new BadDataException("Invalid reseller plan id.");
                }
                if (((_c = resellerPlan.reseller) === null || _c === void 0 ? void 0 : _c.resellerId) !== resellerId) {
                    throw new BadDataException("This plan does not belong to reseller: " + resellerId);
                }
                const licenseKey = req.body.uuid;
                if (!licenseKey) {
                    throw new BadDataException("Invalid license key.");
                }
                const userEmail = new Email(req.body.activation_email);
                if (action === "activate") {
                    // generate a coupon code. Billing is handled by the reseller so OneUptime will have 100% discount on its plans.
                    const couponcode = await BillingService.generateCouponCode({
                        name: resellerId,
                        percentOff: 100,
                        maxRedemptions: 2,
                        durationInMonths: 12 * 20, // 20 years.
                        metadata: {
                            licenseKey: licenseKey || "",
                            resellerPlanId: ((_d = resellerPlan === null || resellerPlan === void 0 ? void 0 : resellerPlan.id) === null || _d === void 0 ? void 0 : _d.toString()) || "",
                        },
                    });
                    // save this in promocode table.
                    const promoCode = new PromoCode();
                    promoCode.promoCodeId = couponcode;
                    promoCode.resellerId = resellerPlan === null || resellerPlan === void 0 ? void 0 : resellerPlan.reseller.id;
                    promoCode.resellerPlanId = resellerPlan === null || resellerPlan === void 0 ? void 0 : resellerPlan.id;
                    promoCode.userEmail = userEmail;
                    promoCode.planType = resellerPlan === null || resellerPlan === void 0 ? void 0 : resellerPlan.planType;
                    promoCode.resellerLicenseId = licenseKey || "";
                    await PromoCodeService.create({
                        data: promoCode,
                        props: {
                            isRoot: true,
                        },
                    });
                    // now redirect to accounts sign up page with this promocode.
                    const accountUrl = await DatabaseConfig.getAccountsUrl();
                    return Response.sendJsonObjectResponse(req, res, {
                        message: "product activated",
                        redirect_url: URL.fromString(accountUrl.toString())
                            .addRoute("/register")
                            .addQueryParams({
                            email: userEmail.toString(),
                            promoCode: couponcode,
                            partnerId: resellerId,
                        })
                            .toString(),
                    }, {
                        statusCode: new StatusCode(201),
                    });
                }
                else if (action === "enhance_tier" || action === "reduce_tier") {
                    // update monitor and team seat limits.
                    const project = await ProjectService.findOneBy({
                        query: {
                            resellerLicenseId: licenseKey,
                        },
                        select: {
                            _id: true,
                        },
                        props: {
                            isRoot: true,
                        },
                    });
                    if (!project) {
                        throw new BadDataException("Project not found with this license key");
                    }
                    // update limits.
                    await ProjectService.updateOneById({
                        id: project.id,
                        data: {
                            activeMonitorsLimit: resellerPlan.monitorLimit,
                            seatLimit: resellerPlan.teamMemberLimit,
                            resellerPlanId: resellerPlan.id,
                        },
                        props: {
                            isRoot: true,
                        },
                    });
                    return Response.sendJsonObjectResponse(req, res, {
                        message: action === "enhance_tier"
                            ? "product enhanced"
                            : "product reduced",
                    });
                }
                else if (action === "refund") {
                    // delete this project.
                    const project = await ProjectService.findOneBy({
                        query: {
                            resellerLicenseId: licenseKey,
                        },
                        select: {
                            _id: true,
                        },
                        props: {
                            isRoot: true,
                        },
                    });
                    if (!project) {
                        // maybe already deleted. so, we just issue a refund and return.
                        return Response.sendJsonObjectResponse(req, res, {
                            message: "product refunded",
                        });
                    }
                    await ProjectService.deleteOneBy({
                        query: {
                            resellerLicenseId: licenseKey,
                            _id: (_e = project.id) === null || _e === void 0 ? void 0 : _e.toString(),
                        },
                        props: {
                            isRoot: true,
                        },
                    });
                    return Response.sendJsonObjectResponse(req, res, {
                        message: "product refunded",
                    });
                }
                throw new BadDataException("Invalid action.");
            }
            catch (err) {
                next(err);
            }
        });
    }
}
//# sourceMappingURL=ResellerPlanAPI.js.map