import { Component, OnDestroy, OnInit, TemplateRef, Input } from "@angular/core";
import { ActivatedRoute, Params } from "@angular/router";
import { takeUntil, finalize } from "rxjs/operators";

import { IUserAccount, Page, GenericResponse, GenericStatus, IResource } from "@shared/models";
import { AppData, HttpService, NotifyService, FinalBillService, PrintOptionService } from "@shared/services";
import { ApiResources, MoneyHelper } from "../../../../../shared/helpers";

import { IChargeModel } from "../../models/charge.model";
import { IPharmacyIndentModel } from "../../models/pharmacy-indent.model";
import { DiscountType } from "../../models/discount-type.model";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { FinalBillBasicModel } from "../../models/final-bill-basic.model";
import { IAdmissionModel } from "../../models/admission.model";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { RepeatType } from "../../models/repeat-type.model";
import { IAdmissionPackageModuleModel } from "../../models/admission-package.model";
import { IReceiptModel } from "../../models/receipt.model";
import { PayType } from "../../models/pay-type.model";
import { ReceiptType } from "../../models/receipt-type.model";
import { AutomaticType } from "../../models/automatic-type.model";
import { ChargeType } from "../../../../../shared/enums";
import { Appointment, InsuranceAdmission } from "../../../../../shared/entities";
import { ILabServicesModel } from "../../models/lab-services.model";
import { Location } from "@angular/common";
import { AdmissionFetchHelper } from "../../../progress-report/shared/helper";
import { NewLabServicesModel } from "../../models/new-lab-services.model";
import { PackageModuleModel } from "../../../masters/pages/package-modules/models";

class ServiceOrder {
    generalRecords: Array<IChargeModel>;
    generalTotal: number;
    pharmacyIndentRecords: Array<IPharmacyIndentModel>;
    pharmacyIndentTotal: number;
    packageRecords: Array<IAdmissionPackageModuleModel>;
    packageTotal: number;
    labServicesRecords: Array<NewLabServicesModel>;
    labServicesTotal: number;
    insuranceForAdmissionId: number;
}

class FinalBill {
    generalRecords: Array<IChargeModel>;
    pharmacyRecords: Array<IChargeModel>;
    packageRecords: Array<IAdmissionPackageModuleModel>;
    labServicesRecords: Array<ILabServicesModel>;
    basics: FinalBillBasicModel;
}

enum EditMode {
    New = 1,
    Final = 2
}

@Component({
    templateUrl: "./final-bill.html",
    styleUrls: ['../../services.css']
})
export class FinalBillPage implements OnInit, OnDestroy {
    page: Page;
    editMode = EditMode;
    discountTypeEnum = DiscountType;
    repeatType = RepeatType;
    automaticType = AutomaticType;
    chargeType = ChargeType;
    receiptType = ReceiptType;
    payType = PayType;
    loading: boolean;
    isChargesLoading: boolean;
    serviceOrder: ServiceOrder;
    chargeRecords: Array<IChargeModel>;

    now: Date;

    submitting: boolean;
    submitted: boolean;
    admissionId: string;
    isAdmission: boolean;
    disableActionBtns: boolean = false;

    finalBillBasics: FinalBillBasicModel;
    appointment: Appointment;

    receipts: Array<IReceiptModel>;

    selectedPackage: PackageModuleModel;
    chargeCategory: IResource;
    departments: Array<string>;
    chargeGroups: Array<string>;
    charges: Array<string>;
    deletedCharges: Array<number>;
    deletedPharmacy: Array<number>;
    deletedLabServices: Array<number>;

    finalBillForm: FormGroup;
    mode: EditMode;

    modalRef: NgbModalRef;
    admission: IAdmissionModel;
    noOfDays: number;
    billNumber: string;
    @Input() isPrintLogo: boolean;
    insuranceAdmission: Array<InsuranceAdmission>;
    insuranceAmount: number;
    constructor(
        private readonly httpService: HttpService,
        private readonly finalBillService: FinalBillService,
        private readonly route: ActivatedRoute,
        private readonly appData: AppData,
        private readonly notifyService: NotifyService,
        private readonly formBuilder: FormBuilder,
        private readonly modalService: NgbModal,
        private readonly location: Location,
        private readonly printOptionService: PrintOptionService,
        private readonly admissionFetchHelper: AdmissionFetchHelper,
    ) {
        this.receipts = new Array<IReceiptModel>();
        this.finalBillBasics = new FinalBillBasicModel();
        this.deletedCharges = new Array<number>();
        this.deletedPharmacy = new Array<number>();
        this.deletedLabServices = new Array<number>();
        this.mode = EditMode.New;
        this.serviceOrder = new ServiceOrder();
        this.serviceOrder.generalRecords = new Array<IChargeModel>();
        this.serviceOrder.pharmacyIndentRecords = new Array<IPharmacyIndentModel>();
        this.serviceOrder.packageRecords = new Array<IAdmissionPackageModuleModel>();
        this.serviceOrder.labServicesRecords = new Array<NewLabServicesModel>();
        this.isChargesLoading = true;
        this.loading = true;
        this.insuranceAdmission = new Array<InsuranceAdmission>();
        this.page = new Page();
        this.buildForm();
    }

    ngOnInit() {
        this.appData.userAccount
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((userAccount: IUserAccount) => {
                if (userAccount) {
                    this.page.userAccount = userAccount;

                    this.route.parent.paramMap
                        .subscribe((params: Params) => {
                            this.admissionId = params["params"]["id"];
                            this.isAdmission = params["params"]["type"] === "a";

                            if (!this.isAdmission)
                                this.getAppointment(this.admissionId);

                            this.getFinalBillBasics(() => {
                                if (this.finalBillBasics.finalAmount !== 0) {
                                    this.admissionFetch();
                                    this.fetchFinal();
                                } else {
                                    this.automatic(() => {
                                        this.admissionFetch();
                                        this.fetchFinal();
                                    });
                                }
                            });


                        });

                } else {
                    this.page.userAccount = undefined;
                }
                this.printOptionService.get((is) => { this.isPrintLogo = is; });
            });
    }

    fetchReceipts = () => {
        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.receipt.base, ApiResources.receipt.fetch), { id: this.admissionId, isAdmission: this.isAdmission, activeOnly: true })
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: GenericResponse) => {
                    const records = response.data as Array<IReceiptModel>;
                    if (records.length > 0) {
                        records.forEach((item) => {
                            item.receiptNo = String(item.receiptId).padStart(6, '0');
                        });
                    }

                    this.receipts = records;
                },
                () => {
                    this.receipts = new Array<IReceiptModel>();
                }
            );

    }

    buildForm = () => {
        this.finalBillForm = this.formBuilder.group({
            discountType: [null],
            discount: [null]
        });

        this.finalBillForm.get("discountType").valueChanges.subscribe((value: DiscountType) => {
            this.finalBillForm.patchValue({ discount: null });

            if (!+value) return;

            const discount = this.finalBillForm.get('discount');
            discount.clearValidators();
            if (+value === DiscountType.Number) {
                discount.setValidators([
                    Validators.min(0),
                    Validators.max(((this.serviceOrder.packageTotal || 0) + (this.serviceOrder.generalTotal || 0) + (this.serviceOrder.labServicesTotal || 0) + (this.serviceOrder.pharmacyIndentTotal || 0)))
                ]);
            } else {
                discount.setValidators([
                    Validators.min(0),
                    Validators.max(100)
                ]);
            }

            discount.updateValueAndValidity();

        });
    }

    get form() {
        return this.finalBillForm.controls;
    }

    get receiptsTotal() {
        if (!this.receipts.length) return 0;
        return this.receipts.filter(x => x.receiptTypeId !== ReceiptType.Refund).map(x => x.cost).reduce((a, b) => a + b, 0);
    }

    get finalAmount() {
        var amount = !+this.finalBillForm.value.discountType
            ? +(((this.serviceOrder.packageTotal || 0) + (this.serviceOrder.generalTotal || 0) + (this.serviceOrder.labServicesTotal || 0) + (this.serviceOrder.pharmacyIndentTotal || 0))).toFixed(2)
            : +(((this.serviceOrder.packageTotal || 0) + (this.serviceOrder.generalTotal || 0) + (this.serviceOrder.labServicesTotal || 0) + (this.serviceOrder.pharmacyIndentTotal || 0)) -
                (
                    (+this.finalBillForm.value.discountType) === DiscountType.Number
                        ? (this.finalBillForm.value.discount || 0)
                        : (((this.serviceOrder.packageTotal || 0) + (this.serviceOrder.generalTotal || 0) + (this.serviceOrder.labServicesTotal || 0) + (this.serviceOrder.pharmacyIndentTotal || 0)) * ((this.finalBillForm.value.discount || 0) / 100))
                )).toFixed(2);

        if (this.insuranceAmount > 0) {
            amount = amount > this.insuranceAmount ? amount - this.insuranceAmount : 0;
        }
        return amount;
    }

    admissionFetch = () => {
        this.admissionFetchHelper.admissionFetch(+this.admissionId, this.isAdmission, (data: IAdmissionModel) => {
            this.loading = false
            this.admission = data;
        });
    }

    onOpenModel(content: TemplateRef<any>) {
        this.now = new Date();
        this.moneyHelper();
        this.modalRef = this.modalService.open(content, {
            backdrop: "static",
            keyboard: false,
            centered: true,
            size: "lg",
            windowClass: "custom-modal slots-modal effect-scale"
        });

        return;
    }

    onCloseModal() {
        try {
            this.modalRef.close();
            this.modalRef = undefined;
        } catch (e) {
            // ignored;
        }

        this.submitting = undefined;
        this.submitted = undefined;
    }

    automatic = (callback?: Function) => {
        var data = {
            id: this.admissionId,
            isAdmission: this.isAdmission,
            createdBy: this.page.userAccount.accountId
        };
        this.httpService
            .post(ApiResources.getURI(ApiResources.serviceOrder.base, ApiResources.serviceOrder.automatic), data)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(() => {
                callback();
            }, () => {
                callback();
            });
    }

    onBack = () => {
        this.location.back();
    }

    getFinalBillBasics = (callback?: Function) => {
        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.getBasics), { id: this.admissionId, isAdmission: this.isAdmission })
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.isChargesLoading = false))
            .subscribe(
                (response: GenericResponse) => {
                    this.finalBillBasics = response.data as FinalBillBasicModel;
                    this.moneyHelper();
                    callback();
                },
                () => {
                    this.finalBillBasics = new FinalBillBasicModel();
                    callback();
                }
            );
    }

    getAppointment = (admissionId: string) => {
        const request = { appointmentId: parseInt(admissionId) };
        this.httpService.post(ApiResources.getURI(ApiResources.appointments.base, ApiResources.appointments.find), request)
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Appointment) => {
                this.appointment = response;
                this.disableActionBtns = this.appointment && this.appointment.status === "C";
            });
    }

    moneyHelper = () => {
        this.finalBillBasics.totalAmountPaidInWords = MoneyHelper.numberCurrencyIn(this.finalBillBasics.totalAmountPaid);
        this.finalBillBasics.totalDueAmountInWords = MoneyHelper.numberCurrencyIn(((this.finalBillBasics.totalAmountPaid - (this.finalAmount || 0)) * -1));
        this.finalBillBasics.totalRefundPendingAmountInWords = MoneyHelper.numberCurrencyIn(((this.finalBillBasics.totalAmountPaid - (this.finalAmount || 0))));
        this.finalBillBasics.netAmountInWords = MoneyHelper.numberCurrencyIn((this.finalAmount || 0));
        this.finalBillBasics.totalAmountInWords = MoneyHelper.numberCurrencyIn(this.finalBillBasics.totalAmount);
    }

    fetchFinal = () => {
        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.fetch),
                {
                    id: this.admissionId, isAdmission: this.isAdmission, modifiedBy: this.page.userAccount.accountId, roleId: this.page.userAccount.roleId, fullName: this.page.userAccount.fullName
                })
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: GenericResponse) => {
                    if (response.status === GenericStatus[GenericStatus.Success]) {
                        const record = response.data as FinalBill;
                        this.chargeCategory = { id: record["roomChargeCategoryId"] || record["chargeCategoryId"], value: record["chargeCategoryName"] } as IResource;

                        if (record.basics && record.basics.finalBillId) {
                            this.billNumber = 'FN' + String(record.basics.finalBillId).padStart(6, '0');
                        }

                        // General Records
                        const generalRecords = record.generalRecords as Array<IChargeModel>;
                        if (generalRecords.length > 0) {
                            const generalSubRecords = new Array<IChargeModel>();
                            generalRecords.forEach(item => {
                                generalSubRecords.push({
                                    serviceOrderId: item.serviceOrderId,
                                    chargeId: item.chargeId,
                                    cost: item.cost,
                                    discount: item.discount,
                                    chargeName: item.chargeName,
                                    chargeGroupName: item.chargeGroupName,
                                    departmentName: item.departmentName,
                                    unit: item.unit,
                                    totalCost: item.cost * item.unit,
                                    status: true,
                                    repeatTypeId: item.repeatTypeId,
                                    chargeTypeMainId: item.chargeTypeMainId,
                                    chargeTypeMainName: item.chargeTypeMainName,
                                    chargeTypeId: item.chargeTypeId,
                                    showAmount: true,
                                    usedQuantity: item.usedQuantity
                                } as IChargeModel);
                            });

                            this.serviceOrder.generalRecords = generalSubRecords;
                            this.serviceOrder.generalTotal = generalSubRecords.map(x => (x.cost * x.unit) - (x.discount || 0)).reduce((a, b) => a + b, 0);

                        } else {
                            this.serviceOrder.generalRecords = new Array<IChargeModel>();;
                            this.serviceOrder.generalTotal = 0;
                        }
                        // Lab Services Records
                        const labServices = record.labServicesRecords as unknown as Array<NewLabServicesModel>;
                        if (labServices.length > 0) {
                            const labServicesSubRecords = new Array<NewLabServicesModel>();
                            labServices.forEach(item => {
                                labServicesSubRecords.push({
                                    labServicesId: item.labServicesId,
                                    labMainDetailId: item.labMainDetailId,
                                    cost: item.cost,
                                    discount: item.discount,
                                    testName: item.testName,
                                    testCode: item.testCode,
                                    unit: item.unit,
                                    totalCost: item.cost * item.unit,
                                    status: true,
                                    repeatTypeId: item.repeatTypeId,
                                    automaticTypeId: item.automaticTypeId,
                                    active: item.active,
                                    createdDate: item.createdDate,
                                    modifiedDate: item.modifiedDate,
                                    createdByName: item.createdByName,
                                    modifiedByName: item.modifiedByName,
                                    isMain: item.isMain,
                                    showAmount: true,
                                    usedQuantity: item.usedQuantity
                                } as unknown as NewLabServicesModel);
                            });

                            this.serviceOrder.labServicesRecords = labServicesSubRecords;
                            this.serviceOrder.labServicesTotal = labServicesSubRecords.filter(x => x.active).map(x => (x.cost * x.unit) - (x.discount || 0)).reduce((a, b) => a + b, 0);
                        } else {
                            this.serviceOrder.labServicesRecords = new Array<NewLabServicesModel>();
                            this.serviceOrder.labServicesTotal = 0;
                        }

                        // Pharmacy Records
                        const pharmacyRecords = record.pharmacyRecords as Array<IChargeModel>;
                        if (pharmacyRecords.length > 0) {
                            const pharmacySubRecords = new Array<IPharmacyIndentModel>();
                            pharmacyRecords.forEach(item => {
                                pharmacySubRecords.push({
                                    pharmacyIssueDetailId: item.productId,
                                    productId: item.productId,
                                    cost: item.cost,
                                    unit: item.unit,
                                    categoryName: item.chargeGroupName,
                                    departmentName: item.departmentName,
                                    productName: item.chargeName,
                                    totalCost: item.cost * item.unit,
                                    discountAmount: (item.cost * item.unit) * item.discountPercentage / 100,
                                    discountPercentage: item.discountPercentage,
                                    status: true,
                                    showAmount: true,

                                } as IPharmacyIndentModel);
                            });

                            this.serviceOrder.pharmacyIndentRecords = pharmacySubRecords;
                            this.serviceOrder.pharmacyIndentTotal = pharmacySubRecords.map(x => (x.cost * x.unit) - x.discountAmount)
                                .reduce((a, b) => a + b, 0);
                        } else {
                            this.serviceOrder.pharmacyIndentRecords = new Array<IPharmacyIndentModel>();;
                            this.serviceOrder.pharmacyIndentTotal = 0;
                        }

                        // Package Records
                        const packageRecords = record.packageRecords as Array<IAdmissionPackageModuleModel>;
                        if (packageRecords.length) {
                            this.serviceOrder.packageRecords = packageRecords;
                            this.serviceOrder.packageTotal = packageRecords.filter(x => x.active).map(x => (x.total)).reduce((a, b) => a + b, 0);
                        } else {
                            this.serviceOrder.packageRecords = new Array<IAdmissionPackageModuleModel>();
                            this.serviceOrder.packageTotal = 0;
                        }

                        this.finalBillForm.patchValue({
                            discountType: record.basics.discountTypeId,
                            discount: record.basics.discountDetails
                        });

                        this.mode = EditMode.Final;
                        this.fetchReceipts();

                    } else {
                        this.mode = EditMode.New;
                        this.fetchServiceOrder();
                    }


                    this.getInsurance();
                },
                () => {
                    this.serviceOrder.generalRecords = new Array<IChargeModel>();;
                    this.serviceOrder.generalTotal = 0;
                    this.serviceOrder.pharmacyIndentRecords = new Array<IPharmacyIndentModel>();;
                    this.serviceOrder.pharmacyIndentTotal = 0;
                    this.serviceOrder.packageRecords = new Array<IAdmissionPackageModuleModel>();
                    this.serviceOrder.packageTotal = 0;
                    this.serviceOrder.labServicesRecords = new Array<NewLabServicesModel>();
                    this.serviceOrder.labServicesTotal = 0;
                }
            );
    }

    calculateTotals = () => {
        this.serviceOrder.generalTotal = this.serviceOrder.generalRecords.filter(x => x.showAmount).map(x => x.cost * x.unit).reduce((a, b) => a + b, 0);
        this.serviceOrder.labServicesTotal = this.serviceOrder.labServicesRecords.filter(x => x.active && x.showAmount).map(x => x.cost * x.unit).reduce((a, b) => a + b, 0);
        this.serviceOrder.pharmacyIndentTotal = this.serviceOrder.pharmacyIndentRecords.filter(x => x.showAmount).map(x => (x.cost * x.unit) - x.discountAmount).reduce((a, b) => a + b, 0);
    }

    fetchServiceOrder = () => {
        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.serviceOrder.base, ApiResources.serviceOrder.fetch), { id: this.admissionId, isAdmission: this.isAdmission, activeOnly: true })
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: GenericResponse) => {
                    this.chargeCategory = { id: response.data["roomChargeCategoryId"] || response.data["chargeCategoryId"], value: response.data["chargeCategoryName"] } as IResource;

                    // General Records
                    const generalRecords = response.data["generalRecords"] as Array<any>;
                    if (generalRecords.length > 0) {
                        const generalSubRecords = new Array<IChargeModel>();
                        generalRecords.forEach(item => {
                            generalSubRecords.push({
                                serviceOrderId: item.serviceOrderId,
                                chargeId: item.chargeId,
                                cost: item.cost,
                                chargeName: item.chargeName,
                                chargeGroupName: item.chargeGroupName,
                                departmentName: item.departmentName,
                                unit: item.unit,
                                totalCost: item.cost * item.unit,
                                discount: item.discount,
                                status: true,
                                repeatTypeId: item.repeatTypeId,
                                automaticTypeId: item.automaticTypeId,
                                chargeTypeMainId: item.chargeTypeMainId,
                                chargeTypeMainName: item.chargeTypeMainName,
                                chargeTypeId: item.chargeTypeId,
                                usedQuantity: item.usedQuantity,
                                showAmount: true
                            } as IChargeModel);
                        });

                        this.serviceOrder.generalRecords = generalSubRecords;
                        this.serviceOrder.generalTotal = generalSubRecords.map(x => (x.cost * x.unit) - (x.discount || 0)).reduce((a, b) => a + b, 0);

                    } else {
                        this.serviceOrder.generalRecords = new Array<IChargeModel>();
                        this.serviceOrder.generalTotal = 0;
                    }

                    // Lab Services Records
                    const labServices = response.data["labServices"] as Array<any>;
                    if (labServices.length > 0) {
                        const labServicesSubRecords = new Array<NewLabServicesModel>();
                        labServices.forEach(item => {
                            labServicesSubRecords.push({
                                labServicesId: item.labServicesId,
                                labMainDetailId: item.labMainDetailId,
                                cost: item.cost,
                                testName: item.testName,
                                testCode: item.testCode,
                                unit: item.unit,
                                totalCost: item.cost * item.unit,
                                discount: item.discount,
                                status: true,
                                repeatTypeId: item.repeatTypeId,
                                automaticTypeId: item.automaticTypeId,
                                active: item.active,
                                createdDate: item.createdDate,
                                modifiedDate: item.modifiedDate,
                                createdByName: item.createdByName,
                                modifiedByName: item.modifiedByName,
                                isMain: item.isMain,
                                usedQuantity: item.usedQuantity,
                                showAmount: true
                            } as unknown as NewLabServicesModel);
                        });

                        this.serviceOrder.labServicesRecords = labServicesSubRecords;
                        this.serviceOrder.labServicesTotal = labServicesSubRecords.filter(x => x.active).map(x => (x.cost * x.unit) - (x.discount || 0)).reduce((a, b) => a + b, 0);
                    } else {
                        this.serviceOrder.labServicesRecords = new Array<NewLabServicesModel>();
                        this.serviceOrder.labServicesTotal = 0;
                    }

                    // Pharmacy Indent Records
                    const pharmacyIndentRecords = response.data["pharmacyIndentRecords"] as Array<any>;
                    if (pharmacyIndentRecords.length > 0) {
                        const pharmacySubRecords = new Array<IPharmacyIndentModel>();
                        pharmacyIndentRecords.forEach(item => {
                            pharmacySubRecords.push({
                                pharmacyIssueDetailId: item.pharmacyIssueDetailId,
                                productId: item.productId,
                                cost: item.cost,
                                unit: item.unit,
                                categoryName: item.categoryName,
                                departmentName: item.departmentName,
                                productName: item.productName,
                                totalCost: item.cost * item.unit,
                                discountAmount: (item.cost * item.unit) * item.discountPercentage / 100,
                                discountPercentage: item.discountPercentage,
                                status: true,
                                showAmount: true
                            } as IPharmacyIndentModel);
                        });

                        this.serviceOrder.pharmacyIndentRecords = pharmacySubRecords;
                        this.serviceOrder.pharmacyIndentTotal = pharmacySubRecords.map(x => (x.cost * x.unit) - x.discountAmount)
                            .reduce((a, b) => a + b, 0);

                    } else {
                        this.serviceOrder.pharmacyIndentRecords = new Array<IPharmacyIndentModel>();
                        this.serviceOrder.pharmacyIndentTotal = 0;
                    }

                    // Package Records
                    const packageRecords = response.data["packageRecords"] as Array<IAdmissionPackageModuleModel>;
                    if (packageRecords.length) {
                        this.serviceOrder.packageRecords = packageRecords;
                        this.serviceOrder.packageTotal = packageRecords.filter(x => x.active).map(x => (x.total)).reduce((a, b) => a + b, 0);
                    } else {
                        this.serviceOrder.packageRecords = new Array<IAdmissionPackageModuleModel>();
                        this.serviceOrder.packageTotal = 0;
                    }

                    this.mode = EditMode.New;
                },
                () => {
                    this.serviceOrder.generalRecords = new Array<IChargeModel>();;
                    this.serviceOrder.generalTotal = 0;
                    this.serviceOrder.pharmacyIndentRecords = new Array<IPharmacyIndentModel>();;
                    this.serviceOrder.pharmacyIndentTotal = 0;
                    this.serviceOrder.packageRecords = new Array<IAdmissionPackageModuleModel>();
                    this.serviceOrder.packageTotal = 0;
                    this.serviceOrder.labServicesRecords = new Array<NewLabServicesModel>();
                    this.serviceOrder.labServicesTotal = 0;
                }
            );
    }

    trackByPackage(_: number, item: PackageModuleModel): number {
        return item.packageModuleId;
    }

    insertHelper = () => {
        if (!this.finalBillForm.valid) return;

        this.submitting = true;

        var data = {
            id: this.admissionId,
            isAdmission: this.isAdmission,
            createdBy: this.page.userAccount.accountId,
            totalAmount: this.serviceOrder.packageTotal + this.serviceOrder.generalTotal + this.serviceOrder.labServicesTotal + this.serviceOrder.pharmacyIndentTotal,
            discountTypeId: this.finalBillForm.value.discountType,
            discountDetails: this.finalBillForm.value.discount,
            finalAmount: this.finalAmount,
            labServices: [],
            generalRecords: [],
            pharmacyRecords: [],
            packageRecords: [],
            roleId: this.page.userAccount.roleId,
            roleName: this.page.userAccount.roleName,
            fullName: this.page.userAccount.fullName
        }

        this.serviceOrder.generalRecords.forEach(item => {
            data.generalRecords.push(
                {
                    chargeId: item.chargeId,
                    unit: item.unit,
                    cost: item.cost,
                    discount: +(item.discount || 0),
                    chargeTypeMainId: item.chargeTypeId ? item.chargeTypeMainId : null,
                    chargeTypeId: item.chargeTypeId,
                });
        });

        this.serviceOrder.labServicesRecords.forEach(item => {
            data.labServices.push(
                {
                    labMainDetailId: item.labMainDetailId,
                    unit: item.unit,
                    cost: item.cost,
                    notes: null
                });
        });

        this.serviceOrder.packageRecords.forEach(item => {
            data.packageRecords.push(
                {
                    packageId: item.packageModuleId,
                    total: item.total
                });
        });

        this.serviceOrder.pharmacyIndentRecords.forEach(item => {
            data.pharmacyRecords.push(
                {
                    productId: item.productId,
                    unit: item.unit,
                    cost: item.cost,
                    discountPercentage: item.discountPercentage,
                });
        });

        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.insert), data)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.submitting = false))
            .subscribe(
                (response: GenericResponse) => {
                    if (response.status === GenericStatus[GenericStatus.Success]) {
                        this.notifyService.success("Final Bill has been Saved successfully");
                        this.mode = EditMode.Final;
                        this.getFinalBillBasics(() => {
                            this.fetchFinal();
                            this.finalBillService.set(true);
                        });
                    } else {
                        if (response.message) {
                            this.notifyService.info(response.message);
                        } else {
                            this.notifyService.defaultError();
                        }
                    }
                },
                () => {
                    this.chargeRecords = new Array<IChargeModel>();
                }
            );
    }

    cancelHelper = () => {
        if (this.finalBillBasics.isDischarged) {
            this.notifyService.info("Final Bill can not be cancelled once the patient is discharged");
            return;
        }

        this.submitting = true;

        var data = {
            id: this.admissionId,
            isAdmission: this.isAdmission,
            createdBy: this.page.userAccount.accountId,
            roleId: this.page.userAccount.roleId,
            roleName: this.page.userAccount.roleName,
            fullName: this.page.userAccount.fullName
        }

        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.cancel),
                data)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.submitting = false))
            .subscribe(
                (response: GenericResponse) => {
                    if (response.status === GenericStatus[GenericStatus.Success]) {
                        this.notifyService.success("Final Bill has been cancelled");
                        this.deletedCharges = new Array<number>();
                        this.deletedLabServices = new Array<number>();
                        this.deletedPharmacy = new Array<number>();
                        this.mode = EditMode.New;
                        this.getFinalBillBasics(() => {
                            this.fetchServiceOrder();
                            this.finalBillService.set(true);
                        });
                    } else {
                        if (response.message) {
                            this.notifyService.info(response.message);
                        } else {
                            this.notifyService.defaultError();
                        }
                    }
                },
                () => {
                    this.chargeRecords = new Array<IChargeModel>();
                }
            );
    }

    resetHelper = () => {
        this.deletedCharges = new Array<number>();
        this.deletedPharmacy = new Array<number>();
        if (this.mode === EditMode.Final) {
            this.fetchFinal();
        } else {
            this.fetchServiceOrder();
        }
    }

    onSubmit = () => {
        if (this.mode === EditMode.New) {
            this.insertHelper();
        } else {
            this.cancelHelper();
        }
    }

    getInsurance() {
        var admissionId = null;
        var appointmentId = null;
        if (this.isAdmission) {
            admissionId = this.admissionId;
        } else {
            appointmentId = this.appointment.appointmentId
        }
        this.httpService.post(ApiResources.getURI(ApiResources.insuranceAdmission.base, ApiResources.insuranceAdmission.getInsuranceApprovals), { admissionId: Number(admissionId), appointmentId: appointmentId })
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => { this.loading = false }))
            .subscribe((response: Array<InsuranceAdmission>) => {
                if (response != undefined && response !== null) {
                    this.insuranceAdmission = response;
                    if (this.insuranceAdmission) {
                        var amount = 0;
                        this.insuranceAdmission.forEach((m) => {
                            amount += m.expectedAmount
                        });
                        this.insuranceAmount = amount;
                    }
                }
            });
    }

    onViewPackage(content: TemplateRef<any>, model: PackageModuleModel): void {
        this.selectedPackage = model;
        this.modalRef = this.modalService.open(content, { size: "lg", windowClass: "custom-modal" });
    }

    onCloseViewPackageModal(): void {
        try {
            this.modalRef.close();
            this.modalRef = undefined;
        } catch (e) {
        }

        this.selectedPackage = undefined;
    }

    ngOnDestroy() {
        this.page.unSubscribe.next();
        this.page.unSubscribe.complete();
    }
}