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

import { IUserAccount, Page, GenericResponse, GenericStatus } from "@shared/models";
import { AppData, HttpService, NotifyService, FinalBillService, 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 { AdmissionFetchHelper } from "../../../progress-report/shared/helper";

enum EditMode {
    New = 1,
    Discharged = 2
}

@Component({
    templateUrl: "./discharge.html",
    styleUrls: ['../../services.css']
})
export class DischargePage 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;
    @Input() isPrintLogo: boolean;
    
    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 admissionFetchHelper: AdmissionFetchHelper,
        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();
                } 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) {
        var disInstructionIds = new Array<number>();
        if (model) {
            model.dischargeInstructionId.split(",").forEach(item => {
                disInstructionIds.push(parseInt(item));
            });
        }
        this.dischargeForm = this.formBuilder.group({
            dischargeDate: [model ? model.dischargeDate : this.datePipe.transform(new Date(), 'yyyy-MM-ddTHH:mm'), [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],
            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]
        });
    }

    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.fetch),
                { 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.admissionFetchHelper.admissionFetch(+this.admissionId, this.isAdmission, (data: IAdmissionModel) => {
            this.loading = false
            this.admission = data;

            if (this.mode === EditMode.New && this.admission.expectedDischargeDate) {
                this.dischargeForm.patchValue({
                    dischargeDate: this.datePipe.transform(new Date(this.admission.expectedDischargeDate), 'yyyy-MM-ddTHH:mm')
                })
            }
        });
    }

    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(",")
        }

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

        console.log(data)

        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.insert), 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;
                        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(",")
        }

        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.update), 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;
                        this.fetch();
                    } else {
                        if (response.message) {
                            this.notifyService.info(response.message);
                        } else {
                            this.notifyService.defaultError();
                        }
                    }
                },
                () => {
                    this.receiptTypes = new Array<IReceiptTypeModel>();
                }
            );
    }

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