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, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, Pagination, IResource } from "@shared/models";
import { DoctorAppointmentNotices } from "@shared/entities/doctor-appointment-notice.entity";
import { NgSelectComponent } from "@ng-select/ng-select";
import { ProviderSpecialization } from "../../../../../shared/entities/provider-specialization.entity";
//import moment = require("moment");
import { DatePipe } from "@angular/common";
import { Role } from "@shared/enums";
import moment from "moment";

class TrackBy {
    doctorAppointmentNotice(item: DoctorAppointmentNotices) {
        return item.doctorAppointmentNoticeId;
    }
}

class DoctorAppointmentNoticeDetails {
    doctorAppointmentNoticeId: number;
    providerId: number;
    machineName: string;
    locationId: number;
    locationName: string;
    fromDate: Date;
    toDate: Date;
    active: boolean;
    description: string;
    providerName: string;
    createdByName: string;
    modifiedByName: string;
    modifiedDate: string;
    createdDate: string;

}

class FilterOptions {
    description: string = null;
    doctorAppointmentNoticeId: number;
    createdBy: number = null;
    locationId: number;
    providerId: number;
    fromDate: string = null;
    toDate: string = null;
    active?: boolean = true;
}

class Filters {
    options: FilterOptions;
    applied: boolean;

    constructor() {
        this.init();
    }

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

@Component({
    templateUrl: "./doctor-appointment-notice.html",
    encapsulation: ViewEncapsulation.None
})

export class DoctorAppointmentNotice implements OnInit, OnDestroy {
    page: Page;
    filters: Filters;
    trackBy: TrackBy;
    pagination: Pagination;
    loading: boolean;
    loadingNotice: boolean;
    modalRef: NgbModalRef;
    doctorAppointmentNoticeForm: FormGroup;
    selectedDoctorAppointmentNotice: DoctorAppointmentNotices;
    submitted: boolean;
    submitting: boolean;
    doctorAppointmentNotice: DoctorAppointmentNoticeDetails[];
    allDoctorAppointmentNotices: DoctorAppointmentNoticeDetails[];
    todayDate: Date;
    greaterThanToday: Date;
    providerSpecialization: ProviderSpecialization[];
    locations: IResource[];
    currentLocation: number;
    minDate: string;
    maxDate: string;
    loadingRoles: boolean;
    accounts: Array<IResource>;

    constructor(
        private readonly appData: AppData,
        private readonly modalService: NgbModal,
        private readonly resourceService: ResourceService,
        private readonly formBuilder: FormBuilder,
        private readonly notifyService: NotifyService,
        private readonly httpService: HttpService,
        private readonly datePipe: DatePipe,
    ) {
        this.loading = true;
        this.page = new Page();
        this.filters = new Filters();
        this.initPagination();
        this.trackBy = new TrackBy();
        this.todayDate = new Date();
        this.buildForm();
        this.allDoctorAppointmentNotices = new Array<DoctorAppointmentNoticeDetails>();
        this.filters.options.fromDate = this.datePipe.transform(new Date(), 'yyyy-MM-dd');
        this.filters.options.toDate = this.datePipe.transform(new Date(), 'yyyy-MM-dd');
    }
    changeMaxDateTime(value: string) {
        this.maxDate = value;
        this.filters.options.toDate = value;
    }

    changeMinDateTime(value: string) {
        this.minDate = value;
        this.filters.options.fromDate = value;
    }

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

    onResetFilters() {
        this.filters.init();
        this.initPagination();
        this.filters.options.locationId = this.page.userAccount.locationId;
        //this.loading = true;
        this.filters.options.fromDate = this.datePipe.transform(new Date(), 'yyyy-MM-dd');
        this.filters.options.toDate = this.datePipe.transform(new Date(), 'yyyy-MM-dd');
        this.fetchDoctorAppointmentNotice();
        this.filters.options.createdBy = null;
    }

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

    private buildForm() {
        this.doctorAppointmentNoticeForm = this.formBuilder.group({
            doctorAppointmentNoticeId: 0,
            description: [null, [Validators.required]],
            providerId: [null, [Validators.required]],
            locationId: [this.currentLocation ? this.currentLocation : null, [Validators.required]],
            fromDate: [null, [Validators.required]],
            toDate: [null, [Validators.required]],
            active: [true],
        });

        //this.doctorAppointmentNoticeForm.get("fromDate").valueChanges.subscribe((value: string) => {
        //    if (value) {
        //        this.greaterThanToday = new Date(value);
        //        if (this.doctorAppointmentNoticeForm.get("toDate").disabled) {
        //            this.doctorAppointmentNoticeForm.get("toDate").setValue(null);
        //        }
        //    }
        //});

        //this.doctorAppointmentNoticeForm.get("locationId").valueChanges.subscribe((value: number) => {
        //    if (value) {
        //        this.fetchDoctorSpecialization(null, value, null, null)
        //        this.doctorAppointmentNoticeForm.get("providerId").setValue(null);
        //    }
        //});
    }

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

    onChangeFromDate(event: any) {
        if (event.doctorAppointmentNoticeForm.value.fromDate) {
            this.greaterThanToday = new Date(event.doctorAppointmentNoticeForm.value.fromDate);
            if (this.doctorAppointmentNoticeForm.get("toDate").disabled) {
                this.doctorAppointmentNoticeForm.get("toDate").setValue(null);
            }
        }
    }

    onChangeLocation(event: IResource) {
        if (event) {
            this.fetchDoctorSpecialization(null, event.id, null, null)
            this.filters.options.providerId = null
        }
    }

   setFocus = (select: NgSelectComponent) => {
        select.open();
    }

    fetchDoctorSpecializationHelper($event: any) {
        if ($event && $event.term && $event.term.length > 1) {
            const locationId = this.doctorAppointmentNoticeForm.get("locationId").value;
            this.fetchDoctorSpecialization($event.term, locationId, null, null);
        } else {
            this.providerSpecialization = new Array<ProviderSpecialization>();
        }
    }

    private fetchDoctorSpecialization(providerId?: string, locationId?: number, consultationTypeId?: number, appointmentDate?: any) {
        var request = {
            filter: providerId,
            locationId: locationId,
            consultationTypeId: consultationTypeId,
            appointmentDate: appointmentDate
        }
        this.loading = true;
        this.httpService
            .post<Array<ProviderSpecialization>>(ApiResources.getURI(ApiResources.appointments.base, ApiResources.appointments.fetchDoctorSpecializationOp), request)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: Array<ProviderSpecialization>) => {
                    if (response.length > 0) {
                        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;
    }

    onOpenModel(content: TemplateRef<any>, doctorAppointmentNotice?: DoctorAppointmentNotices) {
        this.buildForm();
        //this.fetchLocations();
        if (doctorAppointmentNotice) {
            this.selectedDoctorAppointmentNotice = doctorAppointmentNotice;
            this.updateForm();
        }
        this.modalRef = this.modalService.open(content, {
            backdrop: "static",
            keyboard: false,
            centered: true,
            windowClass: "custom-modal effect-scale"
        });
    }


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

    private updateForm() {
        this.doctorAppointmentNoticeForm.patchValue({
            doctorAppointmentNoticeId: this.selectedDoctorAppointmentNotice.doctorAppointmentNoticeId,
            description: this.selectedDoctorAppointmentNotice.description,
            providerId: this.selectedDoctorAppointmentNotice.providerId,
            locationId: this.selectedDoctorAppointmentNotice.locationId,
            fromDate: moment(this.selectedDoctorAppointmentNotice.fromDate).format('YYYY-MM-DD'),
            toDate: moment(this.selectedDoctorAppointmentNotice.toDate).format('YYYY-MM-DD')
        });
        this.fetchDoctorSpecialization(null, this.selectedDoctorAppointmentNotice.locationId, null, null);
    }

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

    fetchDoctorAppointmentNotice() {
        this.loadingNotice = true;
        const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
        if (new Date(request.fromDate).getTime() > new Date(request.toDate).getTime()) {
            this.notifyService.warning("To Date must be greater than From Date!");
            this.loadingNotice = false;
            return;
        }
        this.httpService
            .post<Array<DoctorAppointmentNoticeDetails>>(ApiResources.getURI(ApiResources.doctorAppointmentNotice.base, ApiResources.doctorAppointmentNotice.fetch), request)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loadingNotice = false))
            .subscribe(
                (response: Array<DoctorAppointmentNoticeDetails>) => {
                    this.doctorAppointmentNotice = response;
                    request.active == null ? this.allDoctorAppointmentNotices = response : this.allDoctorAppointmentNotices = response.filter(x => x.active == request.active);
                    UtilHelper.applyPagination(this.doctorAppointmentNotice, this.pagination);
                },
                () => {
                    this.doctorAppointmentNotice = [];
                }
            );
    }

    check(doctorAppointmentNoticeId: number) {
        var isError = false;
        var formValue = this.doctorAppointmentNoticeForm.getRawValue();
        let a = (formValue.fromDate).split('-');
        var fromDate = new Date(a[0], a[1] - 1, a[2]).getTime();
        let b = (formValue.toDate).split('-');
        var toDate = new Date(b[0], b[1] - 1, b[2]).getTime();
        if (doctorAppointmentNoticeId == 0) {
            var testRecords = this.doctorAppointmentNotice.filter(x => x.locationId === formValue.locationId && x.providerId === formValue.providerId);
        }
        else if (doctorAppointmentNoticeId > 0) {
            var testRecords = this.doctorAppointmentNotice.filter(x => x.locationId === formValue.locationId && x.providerId === formValue.providerId && x.doctorAppointmentNoticeId != formValue.doctorAppointmentNoticeId);
        }
        for (var i = 0; i < testRecords.length; i++) {
            var x = testRecords[i];
            var givenFromDate = new Date(x.fromDate).getTime();
            var givenToDate = new Date(x.toDate).getTime();
            var c1 = givenFromDate >= fromDate && givenFromDate <= toDate;
            var c2 = givenToDate >= fromDate && givenToDate <= toDate;
            var c3 = fromDate >= givenFromDate && fromDate <= givenToDate;
            var c4 = toDate >= givenFromDate && toDate <= givenToDate;
            if ((c1 && c2) || (c2 && c3) || (c3 && c4) || (c1 && c4)) {
                if ((!c1 && c3 && c4) || (!c2 && c3 && c4) || (c1 && c2 && c3 && c4)) {
                    this.notifyService.warning('Given Dates already exists with us.');
                }
                else {
                    this.notifyService.warning(`Given Dates are duplicating the existing dates.`);
                }
                isError = true;
                break;
            }
        }
        return isError;
    }

    onSubmit() {
        this.submitted = true;

        if (!this.doctorAppointmentNoticeForm.valid) {
            return;
        }
        const request = Object.assign(UtilHelper.clone(this.doctorAppointmentNoticeForm.getRawValue()));
        if (new Date(request.fromDate).getTime() > new Date(request.toDate).getTime()) {
            this.notifyService.warning("To Date must be greater than From Date!");
            return;
        }
        if (this.check(request.doctorAppointmentNoticeId)) {
            return;
        }
        this.submitting = true;
        request["modifiedByName"] = this.page.userAccount.fullName;
        if (Number(this.doctorAppointmentNoticeForm.value.doctorAppointmentNoticeId) === 0) {
            request.createdBy = this.page.userAccount.accountId;
            this.httpService.post(ApiResources.getURI(ApiResources.doctorAppointmentNotice.base, ApiResources.doctorAppointmentNotice.add), request)
                .pipe(takeUntil(this.page.unSubscribe))
                .pipe(finalize(() => {
                    this.submitting = false;
                    this.submitted = false;
                }))
                .subscribe(() => {
                    this.onCloseModal();
                    this.fetchDoctorAppointmentNotice();
                    this.notifyService.success("Doctor Appointment Notice has been added successfully.");
                }, (error: HttpErrorResponse) => {
                    const errorMessage = UtilHelper.handleError(error);
                    if (errorMessage) {
                        this.notifyService.warning(errorMessage);
                    } else {
                        this.notifyService.defaultError();
                    }
                });
        } else {
            request.modifiedBy = this.page.userAccount.accountId;
            request["modifiedByName"] = this.page.userAccount.fullName;
            request["createdBy"] = this.page.userAccount.accountId;
            delete request.type;
            this.httpService.put(ApiResources.getURI(ApiResources.doctorAppointmentNotice.base, ApiResources.doctorAppointmentNotice.edit), request)
                .pipe(takeUntil(this.page.unSubscribe))
                .pipe(finalize(() => {
                    this.submitting = false;
                    this.submitted = false;
                }))
                .subscribe(() => {
                    this.onCloseModal();
                    this.fetchDoctorAppointmentNotice();
                    this.notifyService.success("Doctor Appointment Notice has been updated successfully.");
                }, (error: HttpErrorResponse) => {
                    const errorMessage = UtilHelper.handleError(error);
                    if (errorMessage) {
                        this.notifyService.warning(errorMessage);
                    } else {
                        this.notifyService.defaultError();
                    }
                });
        }
    }

    private fetchLocations() {
        this.resourceService.locations()
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Array<IResource>) => {
                this.locations = response;
                if (!this.selectedDoctorAppointmentNotice) {
                    this.doctorAppointmentNoticeForm.patchValue({
                        locationId: this.currentLocation
                    });
                }
                this.filters.options.locationId = this.currentLocation;
                this.fetchDoctorSpecialization(null, this.doctorAppointmentNoticeForm.get("locationId").value, null, null);
                this.fetchDoctorAppointmentNotice();
            });
    }


    onModifyStatus(item: DoctorAppointmentNotices, status: boolean) {
        this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this Doctor Appointment Notice?`, () => {
            const request = {
                createdBy: this.page.userAccount.accountId,
                active: status,
                doctorAppointmentNoticeId: item.doctorAppointmentNoticeId,
                description: item.description,
                providerId: item.providerId,
                locationId: item.locationId,
                fromDate: item.fromDate,
                toDate: item.toDate,
                createdByName: this.page.userAccount.fullName,
                createdByRole: this.page.userAccount.roleName,
                loginRoleId: this.page.userAccount.roleId,
            };
            this.loading = true;
            this.httpService.post(ApiResources.getURI(ApiResources.doctorAppointmentNotice.base, ApiResources.doctorAppointmentNotice.modifyStatus), request)
                .pipe(takeUntil(this.page.unSubscribe))
                .pipe(finalize(() => { this.loading = false }))
                .subscribe((response: string) => {
                    if (response) {
                        status ? this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`) : this.notifyService.warningToast(`${status ? 'Activated' : 'Deactivated'} successfully.`)

                    }
                    this.fetchDoctorAppointmentNotice();
                }, (error: HttpErrorResponse) => {
                    this.notifyService.errorToast(error.error);
                });
        });
    }



    onDelete(item: DoctorAppointmentNotices) {

        this.notifyService.delete(() => {
            this.httpService
                .post(ApiResources.getURI(ApiResources.doctorAppointmentNotice.base, ApiResources.doctorAppointmentNotice.delete), {
                    doctorAppointmentNoticeId: item.doctorAppointmentNoticeId, modifiedByName: this.page.userAccount.fullName,
                    createdBy: this.page.userAccount.accountId,
                    modifiedBy: this.page.userAccount.accountId
                })
                .pipe(takeUntil(this.page.unSubscribe))
                .pipe(finalize(() => { }))
                .subscribe(
                    () => {
                        this.notifyService.success("Doctor Appointment Notice deleted successfully.");
                        this.fetchDoctorAppointmentNotice();
                    }, (error: HttpErrorResponse) => {
                        const errorMessage = UtilHelper.handleError(error);
                        if (errorMessage) {
                            this.notifyService.warning(errorMessage);
                        } else {
                            this.notifyService.defaultError();
                        }
                    }
                );
        }, () => { });
    }

    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;
            });
    }

    ngOnInit() {
        this.appData.userAccount
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((userAccount: IUserAccount) => {
                if (userAccount) {
                    this.page.userAccount = userAccount;
                    this.currentLocation = userAccount.locationId;
                    //this.fetchDoctorAppointmentNotice();
                    this.fetchLocations();
                    this.fetchAccounts();
                } else {
                    this.page.userAccount = undefined;
                }
            });
    }

    ngOnDestroy() {
        this.onCloseModal();
        this.page.unsubscribeAll();
    }


}