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 { ChargeCategory } from "@shared/entities/charge-category.entity";
import { WhiteSpaceValidator } from "../../../../../shared/validators";

class TrackBy {
    chargeCategory(item: ChargeCategory) {
        return item.chargeCategoryId;
    }
}

class FilterOptions {
    wardName: string = null;
    departmentId: number;
    chargeGroupId: number;
    repeatTypeId: number;
    chargeCategoryName: string = null;
    chargeCategoryId: number = null;
    //locationId: number;
}

class Filters {
    options: FilterOptions;
    applied: boolean;

    constructor() {
        this.init();
    }

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

@Component({
    templateUrl: "./charge-category.html",
    encapsulation: ViewEncapsulation.None
})
export class ChargeCategoryPage implements OnInit, OnDestroy {
    page: Page;
    filters: Filters;
    trackBy: TrackBy;
    pagination: Pagination;
    loading: boolean;
    modalRef: NgbModalRef;
    submitting: boolean;
    submitted: boolean;
    locations: Array<IResource>;
    selectedChargeCategory: ChargeCategory;
    loadingCategories: boolean;
    categories: Array<ChargeCategory>;
    category: ChargeCategory;
    categoryManagementForm: FormGroup;
    filterchargeCategoryNames = [];

    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
    ) {
        this.loading = true;
        this.page = new Page();
        this.filters = new Filters();
        this.trackBy = new TrackBy();
        this.loading = true;
        this.initPagination();
        this.selectedChargeCategory = new ChargeCategory;
    }

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

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

    onResetFilters() {
        this.filters.init();
        this.initPagination();
        this.loading = true;
        this.fetchChargeCategory();

    }

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

    private filterChargeCategory() {
        this.resourceService.chargeCategory()
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Array<IResource>) => {
                this.filterchargeCategoryNames = response;
            });
    }

    fetchChargeCategory() {
        this.loadingCategories = true;
        const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
        this.httpService.post<Array<ChargeCategory>>(ApiResources.getURI(ApiResources.chargeCategory.base, ApiResources.chargeCategory.fetch), request)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loadingCategories = false))
            .subscribe((response: Array<ChargeCategory>) => {
                this.categories = response;
                UtilHelper.applyPagination(this.categories, this.pagination);
            });
    }

    setDefault(item: ChargeCategory) {
        this.notifyService.confirm("Are you sure to change applied charge to this?", () => {
            this.httpService.post(ApiResources.getURI(ApiResources.chargeCategory.base, ApiResources.chargeCategory.setDefaultCharge), item)
                .pipe(takeUntil(this.page.unSubscribe))
                .pipe(finalize(() => {
                    this.loading = false;
                }))
                .subscribe((response: number) => {
                    if (response > 0) {
                        this.notifyService.successToast("Charge category is in use now.");
                        this.fetchChargeCategory();
                    }
                    else {
                        switch (response) {
                            case -2:
                                this.notifyService.warningToast("Charge category is in Deactive now, Make It as Active And then MAke It Default. ");
                                break;
                        }
                    }
                }, (error: HttpErrorResponse) => {
                    const errorMessage = UtilHelper.handleError(error);
                    if (errorMessage) {
                        this.notifyService.warningToast(errorMessage);
                    } else {
                        this.notifyService.defaultErrorToast();
                    }
                });
        });
    }

    private chargeCategoryForm() {
        this.categoryManagementForm = this.formBuilder.group({
            chargeCategoryId: 0,
            chargeCategoryName: [null, [Validators.required, WhiteSpaceValidator.isValid]],
            active: [true],
            locationIds: [null],
            default: [false]

        });
    }

    onOpenChargeCategoryModel(content: TemplateRef<any>, category?: ChargeCategory) {

        this.chargeCategoryForm();

        if (category) {
            this.category = category;
            this.updateChargeCategoryForm();

            if (category.locationIds) {
                let location = new Array<number>();
                category.locationIds.split(",").forEach((item) => { location.push(parseInt(item)) });
                this.categoryManagementForm.patchValue({
                    locationIds: location
                });
            }
        }

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

    private updateChargeCategoryForm() {
        this.categoryManagementForm.patchValue({
            chargeCategoryId: this.category.chargeCategoryId,
            chargeCategoryName: this.category.chargeCategoryName,
        });
    }

    onSubmit() {
        this.submitted = true;
        if (!this.categoryManagementForm.valid) {
            return;
        }

        this.submitting = true;
        const request = Object.assign(UtilHelper.clone(this.categoryManagementForm.getRawValue()));
        request["loginRoleId"] = this.page.userAccount.roleId,
            request["createdByName"] = this.page.userAccount.fullName
        request["modifiedByName"] = this.page.userAccount.fullName;

        if (request.locationIds) {
            request.locationIds = request.locationIds.join(",")
        }

        if (this.categoryManagementForm.value.chargeCategoryId === 0) {
            request.createdBy = this.page.userAccount.accountId;
            this.httpService.post(ApiResources.getURI(ApiResources.chargeCategory.base, ApiResources.chargeCategory.add), request)
                .pipe(takeUntil(this.page.unSubscribe))
                .pipe(finalize(() => {
                    this.submitting = false;
                    this.submitted = false;
                }))
                .subscribe(() => {
                    this.onCloseModal();
                    this.fetchChargeCategory();
                    this.filterChargeCategory();
                    this.notifyService.success("Charge Categories has been added successfully.");
                }, (error: HttpErrorResponse) => {
                    const errorMessage = UtilHelper.handleError(error);
                    if (errorMessage) {
                        this.notifyService.warning(errorMessage);
                    } else {
                        this.notifyService.defaultError();
                    }
                });
        } else {
            request["modifiedByName"] = this.page.userAccount.fullName;
            request["createdBy"] = this.page.userAccount.accountId;
            request.modifiedBy = this.page.userAccount.accountId;
            this.httpService.put(ApiResources.getURI(ApiResources.chargeCategory.base, ApiResources.chargeCategory.update), request)
                .pipe(takeUntil(this.page.unSubscribe))
                .pipe(finalize(() => {
                    this.submitting = false;
                    this.submitted = false;
                }))
                .subscribe(() => {
                    this.onCloseModal();
                    this.fetchChargeCategory();
                    this.filterChargeCategory();
                    this.notifyService.success("Charge Categories details has been updated successfully.");
                }, (error: HttpErrorResponse) => {
                    const errorMessage = UtilHelper.handleError(error);
                    if (errorMessage) {
                        this.notifyService.warning(errorMessage);
                    } else {
                        this.notifyService.defaultError();
                    }
                });
        }
    }

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

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

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

    onNextPage() {

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

    onModifyStatus(charge: ChargeCategory, status: boolean) {

        this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this charge category?`, () => {
            const request = {
                createdBy: this.page.userAccount.accountId,
                active: status,
                chargeCategoryId: charge.chargeCategoryId,
                createdByName: this.page.userAccount.fullName,
                createdByRole: this.page.userAccount.roleName,
                loginRoleId: this.page.userAccount.roleId,
                chargeCategoryName: charge.chargeCategoryName
            };

            this.httpService.post(ApiResources.getURI(ApiResources.chargeCategory.base, ApiResources.chargeCategory.modifyStatus), request)
                .pipe(takeUntil(this.page.unSubscribe))
                .pipe(finalize(() => { this.loading = false }))
                .subscribe((response: number) => {
                    if (response > 0) {
                        this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`);
                        this.fetchChargeCategory();
                        this.filterChargeCategory();
                    }
                    else {
                        switch (response) {
                            case -2:
                                this.notifyService.warningToast("Charge category is in Default now,  You cannot make it as InActive, Make Some Other Charge Cat as Default Active And then MAke It as InActive. ");
                                break;
                        }
                    }
                }, (error: HttpErrorResponse) => {
                    this.notifyService.errorToast(error.error);
                });
        });
    }

    ngOnInit() {

        this.appData.userAccount
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((userAccount: IUserAccount) => {
                if (userAccount) {
                    this.page.userAccount = userAccount;
                    this.fetchChargeCategory();
                    this.fetchLocations();
                    this.filterChargeCategory();
                } else {
                    this.page.userAccount = undefined;
                }
            });
    }

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