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

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

import { IDischargeModel } from "../../models/discharge.model";
import { LookUpModel } from "../../models/look-up.model";
import { IReceiptTypeModel, ReceiptType } from "../../models/receipt-type.model";
import { PayType } from "../../models/pay-type.model";
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
import { FinalBillBasicModel } from "../../models/final-bill-basic.model";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { IAdmissionModel } from "../../models/admission.model";
import { ImageReports } from "@shared/entities";

enum EditMode {
    New = 1,
    Discharged = 2
}

@Component({
    templateUrl: "./discharge-patient.html",
    styleUrls: ['../../services.css']
})

export class DischargePatientPage implements OnInit, OnDestroy {

    receiptType = ReceiptType;
    payType = PayType;
    editMode = EditMode;
    page: Page;

    loading: boolean;
    isChargesLoading: boolean;
    record: IDischargeModel;
    admission: IAdmissionModel;

    submitting: boolean;
    submitted: boolean;
    admissionId: string;
    isAdmission: boolean;

    isInstructionsLoading: boolean;
    dischargeInstructions: Array<LookUpModel>;
    isStatusLoading: boolean;
    dischargeStatus: Array<LookUpModel>;

    receiptTypes: Array<IReceiptTypeModel>;
    dischargeForm: FormGroup;

    finalBillBasics: FinalBillBasicModel;

    mode: EditMode;
    today = new Date();
    modalRef: NgbModalRef;
    loadingproviderResources: boolean;
    providerResources: Array<IResource>;
    @Input() isPrintLogo: boolean;
    bannerBasics: ImageReports;
    myImgUrl: string = "assets/images/careaxesLogo.png";
    maxDischargeDate: string;

    constructor(
        private readonly httpService: HttpService,
        private readonly route: ActivatedRoute,
        private readonly finalBillService: FinalBillService,
        private readonly appData: AppData,
        private readonly formBuilder: FormBuilder,
        private readonly notifyService: NotifyService,
        private readonly modalService: NgbModal,
        //private readonly datePipe: DatePipe,
        private readonly location: Location,
        private readonly resourceService: ResourceService,
        private readonly printOptionService: PrintOptionService
    ) {
        this.mode = EditMode.New;
        this.record = {} as IDischargeModel;
        this.dischargeInstructions = new Array<LookUpModel>();
        this.dischargeStatus = new Array<LookUpModel>();

        this.finalBillBasics = new FinalBillBasicModel();
        this.isChargesLoading = false;
        this.loading = true;
        this.page = new Page();
        this.buildDischargeForm();
        this.formChanges();
    }

    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";
                            this.getFinalBillBasics(() => {
                                this.admissionFetch();
                                this.fetch();
                                this.getFinalBillBasics();
                            });
                        });
                    this.fetchInstructions();
                    this.fetchStatus();
                    this.fetchProviderResources();
                } else {
                    this.page.userAccount = undefined;
                }
                this.printOptionService.get((is) => { this.isPrintLogo = is; });
            });
    }

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

    get isGeneralInformation() {
        return this.record && Object.keys(this.record).filter(x =>
            x !== "dischargeFollowUpDate" &&
            x !== "dischargeFollowUpDays" &&
            x !== "followUpSummary" &&
            x !== "isDeath" &&
            x !== "deathDate" &&
            x !== "causeOfDeath"
        ).map(x => this.record[x]).filter(x => x).length;
    }

    get isFollowUpInformation() {
        return this.record &&
            Object.keys(this.record).filter(x =>
                x === "dischargeFollowUpDate" ||
                x === "dischargeFollowUpDays" ||
                x === "followUpSummary"
            ).map(x => this.record[x]).filter(x => x).length;
    }

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

    private buildDischargeForm(model?: IDischargeModel) {
        function adjust(val) {
            if (val > 9) {
                return val.toString();
            } else {
                return '0' + val.toString();
            }
        }

        var today = new Date();
        var date = today.getFullYear() + '-' + adjust(today.getMonth() + 1) + '-' + adjust(today.getDate());
        var time = adjust(today.getHours()) + ":" + adjust(today.getMinutes());
        var dateTimeNow = `${date}T${time}`;
        this.maxDischargeDate = `${date}T${time}`;

        var disInstructionIds = new Array<number>();
        if (model && model.dischargeInstructionId) {
            model.dischargeInstructionId.split(",").forEach(item => {
                disInstructionIds.push(parseInt(item));
            });
        }
        var surgeonNamesIds = new Array<number>();
        if (model && model.surgeonNamesId) {
            model.surgeonNamesId.split(",").forEach(item => {
                surgeonNamesIds.push(parseInt(item));
            });
        }

        this.dischargeForm = this.formBuilder.group({
            //dischargeDate: [model ? model.dischargeDate : this.datePipe.transform(new Date(), 'yyyy-MM-ddTHH:mm'), [Validators.required]],
            dischargeDate: [dateTimeNow, [Validators.required]],
            dischargeInstructionId: [model ? disInstructionIds : null],

            dischargeStatusId: [model ? model.dischargeStatusId : null, [Validators.required]],
            //dischargeInstructionName: [model ? model.dischargeInstructionName : null],
            dischargeSummary: [model ? model.dischargeSummary : null],

            conditionOnDischarge: [model ? model.conditionOnDischarge : null],
            finalDiagnosis: [model ? model.finalDiagnosis : null],
            historyOfIllness: [model ? model.historyOfIllness : null],//patients history
            diet: [model ? model.diet : null],

            dischargeFollowUpDate: [model ? model.dischargeFollowUpDate : null],
            dischargeFollowUpDays: [model ? model.dischargeFollowUpDays : null, [Validators.min(1)]],
            followUpSummary: [model ? model.followUpSummary : null],

            isDeath: [model ? model.isDeath : null],
            deathDate: [model ? model.deathDate : null],
            causeOfDeath: [model ? model.causeOfDeath : null],

            pastHistory: [model ? model.pastHistory : null],
            dischargeAdvise: [model ? model.dischargeAdvise : null],
            surgery: [model ? model.surgery : null],
            surgeonNamesId: [model ? surgeonNamesIds : null],
            generalExamination: [model ? model.generalExamination : null],
            localExamination: [model ? model.localExamination : null],
            hospitalCourse: [model ? model.hospitalCourse : null],
            operativeProcedure: [model ? model.operativeProcedure : null],
            operativeNotes: [model ? model.operativeNotes : null],
            consultantSignature: [model ? model.consultantSignature : null],

        });
    }

    onOpenModel(content: TemplateRef<any>) {
        this.getFinalBillBasics();
        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;
    }

    clearDate = (property: string) => {
        this.dischargeForm.patchValue({
            [property]: null
        });
    }

    formChanges = () => {
        this.dischargeForm.get("isDeath").valueChanges.subscribe((value: boolean) => {

            const deathDate = this.dischargeForm.get('deathDate');
            const causeOfDeath = this.dischargeForm.get('causeOfDeath');
            deathDate.clearValidators();
            causeOfDeath.clearValidators();

            if (value) {
                deathDate.setValidators([Validators.required]);
                causeOfDeath.setValidators([Validators.required]);
            }

            deathDate.updateValueAndValidity();
            causeOfDeath.updateValueAndValidity();
        });
    }

    fetch = () => {
        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.dischargefetch),
                { id: this.admissionId })
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: GenericResponse) => {
                    if (response.status === GenericStatus[GenericStatus.Success]) {
                        this.mode = EditMode.Discharged;
                        const record = response.data as IDischargeModel;
                        record.dischargeSummaryView = record.dischargeSummary
                            ? record.dischargeSummary.replace(/\n/g, "<br />")
                            : record.dischargeSummary;
                        this.buildDischargeForm(record);
                        this.record = record;
                    } else if (response.status === GenericStatus[GenericStatus.Error]) {
                        this.mode = EditMode.Discharged;
                        this.notifyService.defaultError();
                    } else {
                        this.mode = EditMode.New;
                    }
                },
                () => {
                    this.record = null;
                }
            );

    }

    admissionFetch = () => {
        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.serviceOrder.base, ApiResources.serviceOrder.getAdmissionBasic),
                { id: this.admissionId, isAdmission: this.isAdmission })
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: GenericResponse) => {
                    if (response.status === GenericStatus[GenericStatus.Success]) {
                        this.admission = response.data as IAdmissionModel;
                        //if (this.mode === EditMode.New && this.admission.expectedDischargeDate) {
                        //    this.dischargeForm.patchValue({
                        //        dischargeDate: this.datePipe.transform(new Date(this.admission.expectedDischargeDate), 'yyyy-MM-ddTHH:mm')
                        //    })
                        //}
                    }
                },
                () => {
                    this.admission = null;
                }
            );
    }

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

    fetchInstructions = () => {
        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.fetchInstructions), {})
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.isInstructionsLoading = false))
            .subscribe(
                (response: GenericResponse) => {
                    this.dischargeInstructions = response.data as Array<LookUpModel>;
                },
                () => {
                    this.dischargeInstructions = new Array<LookUpModel>();
                }
            );
    }

    fetchStatus = () => {
        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.fetchStatus), {})
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.isStatusLoading = false))
            .subscribe(
                (response: GenericResponse) => {
                    this.dischargeStatus = response.data as Array<LookUpModel>;
                },
                () => {
                    this.dischargeStatus = new Array<LookUpModel>();
                }
            );
    }

    insert = () => {
        this.submitted = true;
        if (!this.dischargeForm.valid) {
            return;
        }

        this.submitting = true;
        const data = {
            ...this.dischargeForm.value,
            createdBy: this.page.userAccount.accountId,
            id: this.admissionId,
        };

        if (data.dischargeInstructionId) {
            data.dischargeInstructionId = data.dischargeInstructionId.join(",")
        }

        if (data.surgeonNamesId) {
            data.surgeonNamesId = data.surgeonNamesId.join(",")
        }

        data["createdBy"] = this.page.userAccount.accountId;
        data["roleId"] = this.page.userAccount.roleId;
        data["fullName"] = this.page.userAccount.fullName;


        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.dischargeinsert), data)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.submitting = false))
            .subscribe(
                (response: GenericResponse) => {
                    if (response.status === GenericStatus[GenericStatus.Success]) {
                        this.notifyService.success("Patient  has been discharged successfully");
                        this.mode = EditMode.Discharged;

                    } if (response.status === GenericStatus[GenericStatus.Info]) {
                        this.notifyService.warningToast("Patient cannot be discharged.");
                    }
                    this.admissionFetch();
                    this.fetch();
                    this.finalBillService.set(true);
                    //else {
                    //    if (response.message) {
                    //        this.notifyService.info(response.message);
                    //    } else {
                    //        this.notifyService.defaultError();
                    //    }
                    //}
                },
                () => {
                    //this.notifyService.defaultError();
                }
            );
    }

    onSubmit = () => {

        if (this.record.dischargeId) {
            this.update();
        } else {
            this.insert();
        }
    }

    onEdit = () => {
        this.mode = EditMode.New;
    }

    onCancel = () => {
        this.mode = EditMode.Discharged;
    }

    update = () => {
        this.submitted = true;
        if (!this.dischargeForm.valid) {
            return;
        }

        this.submitting = true;
        const data = {
            ...this.dischargeForm.value,
            id: this.record.dischargeId.toString(),
            modifiedBy: this.page.userAccount.accountId
        };

        if (data.dischargeInstructionId) {
            data.dischargeInstructionId = data.dischargeInstructionId.join(",")
        }

        if (data.surgeonNamesId) {
            data.surgeonNamesId = data.surgeonNamesId.join(",")
        }

        data["modifiedBy"] = this.page.userAccount.accountId;
        data["roleId"] = this.page.userAccount.roleId;
        data["fullName"] = this.page.userAccount.fullName;

        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.dischargeupdate), data)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.submitting = false))
            .subscribe(
                (response: GenericResponse) => {
                    if (response.status === GenericStatus[GenericStatus.Success]) {
                        this.notifyService.success("Patient Discharged details has been Updated successfully");
                        this.mode = EditMode.Discharged;
                        this.fetch();
                    } else {
                        if (response.message) {
                            this.notifyService.info(response.message);
                        } else {
                            this.notifyService.defaultError();
                        }
                    }
                },
                () => {
                    this.receiptTypes = new Array<IReceiptTypeModel>();
                }
            );
    }

    private fetchProviderResources() {
        this.loadingproviderResources = true;
        this.resourceService.providerNames()
            .pipe(finalize(() => { this.loadingproviderResources = false }))
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Array<IResource>) => {
                this.providerResources = response;
            });
    }

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