import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, FormBuilder, FormArray, Validators } from "@angular/forms";
import { Page, IUserAccount, Pagination, IResource, GenericResponse } from "@shared/models";
import { LookUpModel } from "../../../services/models/look-up.model";
import { ProviderSpecialization } from "../../../../../shared/entities/provider-specialization.entity";
import { ProviderScheduleVisits } from "../../../../../shared/entities";
import { Role } from "@shared/enums";
import { Router } from "@angular/router";
class TrackBy {
    providerSchedulerCharges(item: ProviderScheduleVisits) {
        return item.providerId;
    }
}

class FilterOptions {
    locationId: number = null;
    providerId: number = null;
    specializationId: number = null;
    departmentId: number = null;
    createdBy: number = null;
    active: boolean = true;
}

class Filters {
    options: FilterOptions;
    applied: boolean;

    constructor() {
        this.init();
    }

    init() {
        this.options = new FilterOptions();
        this.applied = undefined;
    }
}

@Component({
    templateUrl: "./provider-schedule-visits.html",
    encapsulation: ViewEncapsulation.None
})
export class ProviderScheduleVisitsPage implements OnInit, OnDestroy {
    page: Page;
    filters: Filters;
    trackBy: TrackBy;
    pagination: Pagination;
    providerScheduleVisitForm: FormGroup;
    loading: boolean;
    providerSchedulerVisits: Array<ProviderScheduleVisits>;
    providerSchedulerVisitType: Array<ProviderScheduleVisits>;

    modalRef: NgbModalRef;
    submitting: boolean;
    submitted: boolean;
    modifying: boolean;
    modifyingContent: string;

    locations: Array<IResource>;

    visitors: Array<LookUpModel>;
    charges: Array<LookUpModel>;
    loadingSpecializationResources: boolean;
    loadingproviderResources: boolean;
    currencySymbol = "₹";

    providerSpecialization: Array<ProviderSpecialization>

    isVisitTypeloading: boolean;

    chargeDurationForm: FormGroup;
    doctorCharges: Array<ProviderScheduleVisits>;
    loadingSpecialization: boolean;
    specializations: Array<IResource>;
    loadingProviders: boolean;
    providers: Array<IResource>;
    locationId: number;
    accounts: Array<IResource>;
    loadingRoles: boolean;
    encryptedProviderId: string;
    currentLocation: number;
    providerId: number;
    constructor(
        private readonly appData: AppData,
        private readonly modalService: NgbModal,
        private readonly formBuilder: FormBuilder,
        private readonly notifyService: NotifyService,
        private readonly httpService: HttpService,
        private readonly resourceService: ResourceService,
        private readonly router: Router,
    ) {
        this.buildForm();
        this.page = new Page();
        this.filters = new Filters();
        this.trackBy = new TrackBy();
        this.initPagination();
        this.locations = new Array<IResource>();
        this.doctorCharges = new Array<ProviderScheduleVisits>();
        this.specializations = new Array<IResource>();
        this.providers = new Array<IResource>();
        this.providerSchedulerVisits = new Array<ProviderScheduleVisits>();
    }

    private initPagination() {
        this.pagination = new Pagination();
        this.pagination.pageIndex = 1;
        this.pagination.pageSize = 10;
    }

    private fetchAccounts() {
        this.loadingRoles = true;
        const roleId = Role.Patient.toString();
        this.resourceService.getAllAccountsExpectPassedRoleId(roleId)
            .pipe(finalize(() => { this.loadingRoles = false }))
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Array<IResource>) => {
                this.accounts = response;
            });
    }
    private buildForm() {
        this.providerScheduleVisitForm = this.formBuilder.group({
            providerAvailabilityVisitTypeId: 0,
            locationId: [this.currentLocation ? this.currentLocation : null, [Validators.required]],
            specializationId: [null],
            providerId: [this.encryptedProviderId != null || this.encryptedProviderId != undefined ? this.providerId : null],
            active: [true],
            visits: this.formBuilder.array([])
        });

        this.providerScheduleVisitForm.get("locationId").valueChanges.subscribe((value: number) => {
            if (value) {
                this.fetchDoctorSpecialization(null)
            } else {
                return this.providerSpecialization = undefined;
            }

        })
    }

    get chargeType() {
        return this.chargeDurationForm.controls;
    }

    get chargeTypeFormArray() { return this.chargeDurationForm.controls["charges"] as FormArray }

    get chargeForm() {
        return this.chargeTypeFormArray;
    }

    addChargesToArray(typeId?: number, value?: number) {
        return this.formBuilder.group({
            chargeTypesId: [typeId ? typeId : null],
            chargeTypeCharge: [value ? value : null],
        });
    }

    addChargeTypeToArray(mainItem: LookUpModel, chargeValue?: string) {
        return this.formBuilder.group({
            typeId: [mainItem.id],
            name: [mainItem.name],
            value: [chargeValue ? chargeValue : 0]
        });
    }

    onOpenModel(content: TemplateRef<any>, providerScheduleVisit?: ProviderScheduleVisits) {
        this.buildForm();
        if (providerScheduleVisit != undefined) {
            this.fetchDoctorCharge(providerScheduleVisit);

        }

        if (providerScheduleVisit == undefined || providerScheduleVisit == null) {
            this.fetchAddVisitTypes();
        }
        this.modalRef = this.modalService.open(content, {
            backdrop: "static",
            keyboard: false,
            centered: true,
            windowClass: "custom-modal effect-scale"
        });
    }

    onChangeProvider(p: ProviderSpecialization) {
        this.filters.options.specializationId = p.specializationId;
        // console.log(a);
    }

    fetchDoctorCharge(providerScheduleCharge?: ProviderScheduleVisits) {
        const request = {}
        if (providerScheduleCharge != undefined) {
            request["providerId"] = providerScheduleCharge.providerId;
            request["specializationId"] = providerScheduleCharge.specializationId;
        }
        
        this.httpService
            .post<Array<ProviderScheduleVisits>>(ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.doctorVisit), request)

            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: Array<ProviderScheduleVisits>) => {
                    

                    this.doctorCharges = response;
                    let abc = [] // provider availability visit types with values

                    for (var item of response) {
                        abc.push({ id: item.id, name: item.name, value: item.value, providerAvailabilityVisitTypeId: item.providerAvailabilityVisitTypeId });
                    }
                    console.log(abc);
                    let visit = [] //visit types from masters for OP 

                    for (var visittype of this.charges) { 
                        visit.push({ id: visittype.id, name: visittype.name, value: 0, providerAvailabilityVisitTypeId: 0 })
                    }

                    visit.forEach(x => { // values which are not present in abc and present in visit pushed to abc. 
                        if (!abc.find(y => y.id === x.id)) {
                            abc.push(x);
                        }
                    });
                    
                    if (providerScheduleCharge) {
                        abc.forEach((item) => {
                            this.forms.visitArray.push(this.buildChargeForm(item));
                        });
                        this.doctorCharges.forEach((data) => {
                            this.providerScheduleVisitForm.patchValue({
                                providerId: data.providerId,
                                specializationId: data.specializationId,
                                startDate: data.startDate,
                                endDate: data.endDate,
                                providerAvailabilityVisitTypeId: data.providerAvailabilityVisitTypeId,
                                locationId: data.locationId,
                                visitTypeId: data.visitTypeId
                            })
                        })
                    }

                },
                () => {
                    this.doctorCharges = new Array<ProviderScheduleVisits>();
                }
            );
    }

    //onChangeProvider(event: ProviderSpecialization) {
    //    this.providerScheduleVisitForm.patchValue({
    //        specializationId: event.specializationId
    //    });

    //    this.filters.options.specializationId = event.specializationId;
    //    this.filters.options.departmentId = event.departmentId;
    //}

    //onChangeLocation(event: IResource) {
    //    this.fetchDoctorSpecialization(null, event.id)
    //}

    fetchProviderScheduleCharges() {
        this.loading = true;

        const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
        if (!request.locationId) {
            request.locationId = this.page.userAccount.locationId;
        }
        if (!request.providerId) {
            request.specializationId = null;
        }
        if (this.encryptedProviderId != null || this.encryptedProviderId != undefined) {
            request["encryptedProviderId"] = this.encryptedProviderId;
        }
        this.providerSchedulerVisits = new Array<ProviderScheduleVisits>();
        this.httpService
            .post<Array<ProviderScheduleVisits>>(ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.fetch), request)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: any) => {

                    this.providerSchedulerVisits = response;
                    UtilHelper.applyPagination(this.providerSchedulerVisits, this.pagination);
                },
                () => {
                    this.providerSchedulerVisits = [];
                }
            );
    }

    onNextPage() {
        $("body,html").animate({ scrollTop: 0 });
        this.fetchProviderScheduleCharges();
    }

    onSubmit() {
        this.submitted = true;
        if (!this.providerScheduleVisitForm.valid) {
            this.notifyService.warningToast("Please fill all fields.")
            return;
        }
        const request = Object.assign(UtilHelper.clone(this.providerScheduleVisitForm.getRawValue()));
        let abc = request.visits.filter(m => m.value == null);
        if (abc.length > 0) {
            return this.notifyService.warningToast("Please provide Charge amount");
        }
        request["modifiedByName"] = this.page.userAccount.fullName;
        request["visits"] = this.providerScheduleVisitForm.value.visits;

        request.createdBy = this.page.userAccount.accountId;
        if (request["providerAvailabilityVisitTypeId"] > 0) {
            request["modifiedBy"] = this.page.userAccount.accountId;
        }
        this.submitting = true;
        var url = ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.add);
        if (request["providerAvailabilityVisitTypeId"] > 0) {
            url = ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.update);
        }
        this.httpService.post(url, request)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => {
                this.submitting = false;
                this.submitted = false;
            }))
            .subscribe(() => {
                this.onCloseModal();
                this.fetchProviderScheduleCharges();
                this.notifyService.successToast(`Record ${request["providerAvailabilityVisitTypeId"] > 0 ? 'updated' : 'added'} successfully.`);
                //this.notifyService.successToast("provider Schedule Visits has been added successfully.");
            }, (error: HttpErrorResponse) => {
                const errorMessage = UtilHelper.handleError(error);
                if (errorMessage) {
                    this.notifyService.warningToast(errorMessage);
                } else {
                    this.notifyService.defaultError();
                }
            });
    }

    get forms() {
        return {
            form: this.providerScheduleVisitForm ? this.providerScheduleVisitForm.controls : {},
            visitArray: this.providerScheduleVisitForm.controls["visits"] as FormArray,
        }
    }

    private buildChargeForm(charge: any) {
        return this.formBuilder.group({
            id: charge.id,
            name: charge.name,
            value: charge.value ? charge.value : 0,
            providerAvailabilityVisitTypeId: charge.providerAvailabilityVisitTypeId ? charge.providerAvailabilityVisitTypeId : 0
        });
    }

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

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

    ngOnInit() {
        this.appData.userAccount
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((userAccount: IUserAccount) => {
                if (userAccount) {
                    
                    this.page.userAccount = userAccount;
                    this.currentLocation = this.page.userAccount.locationId;
                    const url = this.router.url;
                    this.encryptedProviderId = url.split("/")[url.split("/").length - 2];
                    if (this.encryptedProviderId == "masters") {
                        this.encryptedProviderId = null;
                    }
                    this.buildForm();
                    this.fetchLocations();
                    this.fetchAccounts();
                    this.fetchProviderScheduleCharges();
                    this.fetchLocationSpecialization(this.page.userAccount.locationId);
                    this.fetchProviders(this.page.userAccount.locationId);
                    this.fetchAddVisitTypes();
                } else {
                    this.page.userAccount = undefined;
                }
            });
    }

    private fetchLocations() {
        this.resourceService.locations()
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Array<IResource>) => {
                this.locations = response;
                this.filters.options.locationId = this.page.userAccount.locationId;

                this.fetchDoctorSpecialization(this.filters.options.locationId)
            });
    }

    fetchAddVisitTypes() {
        this.httpService
            .post<GenericResponse>(ApiResources.getURI(ApiResources.providerLocations.base, ApiResources.providerLocations.fetchVisitTypes), {})
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: GenericResponse) => {
                    this.charges = response.data as Array<LookUpModel>;
                    this.charges.forEach((charge) => {
                        const item = {
                            id: charge.id,
                            name: charge.name,
                            value: charge.value ? charge.value : 0
                        };

                        this.forms.visitArray.push(this.buildChargeForm(item));
                    });
                },
                () => {
                    this.charges = new Array<LookUpModel>();
                }
            );
    }


    private fetchDoctorSpecialization(locationId?: number) {

        this.loading = true;
        var request = {
            locationId: locationId
        }

        this.httpService
            .post<Array<ProviderSpecialization>>(ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.fetchProviderSpecialization), request)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: Array<ProviderSpecialization>) => {
                    this.providerSpecialization = response;
                },
                () => {
                    this.providerSpecialization = new Array<ProviderSpecialization>();
                }
            );
    }

    customSearch(term: string, item) {

        term = term.toLocaleLowerCase();
        return item['fullName'].toLocaleLowerCase().indexOf(term) > -1 || item['specializationName'].toLocaleLowerCase().indexOf(term) > -1;
    }

    onApplyFilters() {
        this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
        this.initPagination();
        this.loading = true;
        this.fetchProviderScheduleCharges();
    }

    onResetFilters() {
        this.filters.init();
        this.loading = true;
        this.filters.options.locationId = this.page.userAccount.locationId;
        this.fetchProviderScheduleCharges();
        this.fetchLocationSpecialization(this.page.userAccount.locationId);
    }
    onProviderSelect(provider?: IResource) {
        if (provider != undefined) {
            this.fetchProviderSpecializations(provider.id);
        } if (provider == undefined) {
            this.fetchLocationSpecialization(this.page.userAccount.locationId);
        }
        //this.fetchProviderSpecializations(provider.id);
        if (provider) {
            this.providerId = provider.id;
            this.providerScheduleVisitForm.patchValue({
                providerId: provider.id ? provider.id : null
            });
        } else {
            this.providerScheduleVisitForm.patchValue({
                providerId: null
            });
        }
    }

    providerChange() {
        this.filters.options.specializationId = 1;
    }
    private fetchProviderSpecializations(providerId?: number) {
        this.loadingSpecialization = true;
        if (this.encryptedProviderId != null || this.encryptedProviderId != undefined) {
            var encryptedProviderId = this.encryptedProviderId;
        }
        this.resourceService.providerSpecializations(providerId, encryptedProviderId, )
            .pipe(finalize(() => { this.loadingSpecialization = false }))
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Array<IResource>) => {
                this.specializations = response;
            });
    }
    private fetchProviders(locationId?: number) {
        
        this.loadingProviders = true;
        if (this.encryptedProviderId != null || this.encryptedProviderId != undefined) {
            var encryptedProviderId = this.encryptedProviderId;
        }
        
        this.resourceService.locationProviders(locationId, encryptedProviderId)
            .pipe(finalize(() => { this.loadingProviders = false }))
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Array<IResource>) => {
                this.providers = response;
                if (this.encryptedProviderId != null || this.encryptedProviderId != undefined) {
                    this.onProviderSelect(response[0])
                }

            });
    }
    private fetchLocationSpecialization(locationId?: number) {
        this.loadingSpecialization = true
        if (this.encryptedProviderId != null || this.encryptedProviderId != undefined) {
            var encryptedProviderId = this.encryptedProviderId;
        }
        this.resourceService.locationSpecializations(locationId, encryptedProviderId)
            .pipe(finalize(() => { this.loadingSpecialization = false }))
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Array<IResource>) => {
                this.specializations = response;
            });
    }
    onChangeLocation(event: IResource) {
        this.locationId = event.id;
        this.fetchDoctorSpecialization(null)
        this.fetchLocationSpecialization(event.id);
        this.fetchProviders(event.id);
    }
    onChangeFilterLocation(event: IResource) {
        this.locationId = event.id;
        this.fetchLocationSpecialization(event.id);
        this.fetchProviders(event.id);
    }

    onChangeStatus(record: ProviderScheduleVisits, status: boolean) {
        const request = {
            schedulerTypeId: record.schedulerTypeId,
            active: status,
            modifiedBy: this.page.userAccount.accountId,
            roleId: this.page.userAccount.roleId
        };
        this.notifyService.confirm(`Do you really want to ${status ? "Active" : "Inactive"} this selected Charges?`, () => {
            this.modifying = true;
            this.modifyingContent = `${status ? "activating" : "inactivating"} the selected Component`;
            this.httpService
                .post(ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.modifyStatus), request)
                .pipe(takeUntil(this.page.unSubscribe))
                .pipe(finalize(() => { this.modifying = false }))
                .subscribe(
                    (response: number) => {
                        if (response > 0) {
                            switch (response) {
                                case 1:
                                    this.notifyService.successToast("Status is updated successfully.");
                                    this.fetchProviderScheduleCharges();
                            }
                        }
                        this.fetchProviderScheduleCharges();

                    },
                    () => {

                    }
                );

        }, () => {

        });
    }
    ngOnDestroy() {
        this.onCloseModal();
        this.page.unsubscribeAll();
    }
    fetchDoctorSpecializationHelper($event: any) {
        if ($event && $event.term && $event.term.length > 1) {
            // let locationId = this.quickScheduleForm.get("locationId").value
            //  let consultationTypeId = this.quickScheduleForm.get("consultationTypeId").value
            this.fetchDoctorSpecialization(this.page.userAccount.locationId);
        } else {
            this.providerSpecialization = new Array<ProviderSpecialization>();
        }
    }

}