// Angular Core
import { formatDate } from '@angular/common';
import { HttpErrorResponse } from '@angular/common/http';
import { Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';

// RxJs
import { Subscription, catchError, throwError } from 'rxjs';

// Pipes
import { StripNDCPipe } from 'src/app/filters/strip-ndc.pipe';

// Services
import { SessionService } from 'src/app/services/session/session.service';
import { SupplierCatalogService } from 'src/app/services/supplierCatalog/supplier-catalog.service';
import { ExportFileService } from 'src/app/feature-modules/auth/services/exportFile/export-file.service';

// Interfaces
import { SessionDataInterface } from 'src/app/interfaces/session-data-interface';
import { ActiveProductsInterface } from 'src/app/interfaces/supplier/active-products-interface';

import { NgbModal, NgbModalConfig, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { UtilitiesService } from 'src/app/services/utilities/utilities.service';
import { Table } from 'primeng/table';

@Component({
  standalone: false,
    selector: 'app-active-products',
    templateUrl: './active-products.component.html',
    styleUrls: ['./active-products.component.scss', './active-products.component.query.scss']
})
export class ActiveProductsComponent implements OnInit, OnDestroy {

    @ViewChild('deleteProductModal') deleteProductModalRef !: ElementRef;
    @ViewChild('allocationModal') allocationModalRef !: ElementRef;

    session!: SessionDataInterface['data'];
    renderMe!: boolean;

    activeProducts!: ActiveProductsInterface['data']['products'];
    uniqueEndDates!: ActiveProductsInterface['data']['uniqueEndDates'];
    minDate: Date = new Date();
    
    auctionId!: number;
    totalActiveProducts!: number;
    isLoading: boolean = false;
    showDates: boolean = false;
    rowEditable: boolean[] = [];
    enableUpdateButton: boolean = false;
    searchType: string = '';
    selectedDate: string[] = [];
    endTime!: string;
    allocAuctionId!: number;
    ndcLevelAllocReqd: number = 0;
    allocNdc!: string;
    ndcAllocation!: number;
    /**
    * If Supplier, is Prime Supplier then isPrimeSupplier will be set to true, by default it is set to false.
    * @type boolean
    */
    isPrimeSupplier: boolean = false;

    // Error handling Variables
    showStatus: boolean = false;
    statusType!: string;
    statusMsg!: string;
    productToEdit!: ActiveProductsInterface['data']['products'][0];
    @ViewChild(Table) tableComponent!: Table;
    errorField = '';

    constructor(
        private sessionService: SessionService,
        private stripNDCPipe: StripNDCPipe,
        private supplierCatalogService: SupplierCatalogService,
        private exportFileService: ExportFileService,
        private ngbModalconfig: NgbModalConfig,
        private modalService: NgbModal,
        private utilities: UtilitiesService
    ) {
        this.ngbModalconfig.backdrop = 'static';
        this.ngbModalconfig.keyboard = false;
    }

    ngOnInit(): void {
        this.session = this.sessionService.getSession();
        this.renderMe = this.session.logged_in && (this.session.reg_step > 6) && this.session.is_supplier;
        this.searchActiveProducts('onload');
    }

    /**
    * Search Data Parameters
    */
    supplierProductData: any = {
        searchData: {
            ndc: "",
            productName: "",
            supplierProdId: ""
        }
    };

    /**
    * Search Active Products
    * @returns {undefined}
    */
    getActiveProductsSubscribe!: Subscription;
    searchActiveProducts(type: string) {
        this.isLoading = true;
        this.ndcLevelAllocReqd = 0;
        this.allocNdc = "";
        this.searchType = type;
        if (type === 'search') {
            this.statusMsg = '';
            this.showStatus = false;
        }
        // TRX-8003
        this.supplierProductData.searchData.ndc = this.stripNDCPipe.transform(this.supplierProductData.searchData.ndc.trim());
        this.supplierProductData.searchData.productName = this.supplierProductData.searchData.productName.trim();
        this.supplierProductData.searchData.supplierProdId = this.supplierProductData.searchData.supplierProdId.trim();
        this.getActiveProductsSubscribe = this.supplierCatalogService.getActiveProducts(this.supplierProductData)
            .pipe(
                catchError((err) => {
                    this.isLoading = false;
                    this.showStatus = true;
                    this.statusType = 'error';
                    if (err.error.feedback) {
                        this.statusMsg = "Error Performing search";
                    }
                    return throwError(() => new Error('ups sommething happend'));
                })
            )
            .subscribe({
                next: (res: ActiveProductsInterface) => {
                    this.activeProducts = res.data.products;
                    this.totalActiveProducts = res.data.total;
                    this.uniqueEndDates = res.data.uniqueEndDates;
                    this.isPrimeSupplier = res.data.isPrimeSupplier;
                    this.isLoading = false;
                },
                error: (err: HttpErrorResponse) => {
                    this.isLoading = false;
                    this.showStatus = true;
                    this.statusType = 'error';
                    if (err.error.feedback) {
                        this.statusMsg = "Error Performing search";
                    }
                },
                complete: () => { },
            })
    };

    /**
    * Method will display unique endDate list
    * @returns {undefined}
    */
    showListDate() {
        this.showDates = !this.showDates;
    };

    /**
     * Method will update active products list by selected Date
     * @param string endDate
     * @returns {undefined}
     */
    updateActiveProductsSubscribe!: Subscription;
    updateActiveProducts(endDate: string) {
        this.enableUpdateButton = false;
        this.showDates = false;
        var datesArray = this.convertDateFormat(this.selectedDate);
        endDate = this.dateFormat(endDate);
        this.updateActiveProductsSubscribe = this.supplierCatalogService.updateActiveProducts(this.supplierProductData, endDate, datesArray)
            .pipe(
                catchError((err) => {
                    this.showStatus = true;
                    this.statusType = "error";
                    this.statusMsg = err.error.feedback[0];
                    return throwError(() => new Error('ups sommething happend'));
                })
            )
            .subscribe({
                next: () => {
                    this.selectedDate = [];
                    this.showStatus = true;
                    this.statusType = "success";
                    this.statusMsg = "Product Updated Successfully";
                    this.searchActiveProducts('update');
                },
                error: (err: HttpErrorResponse) => {
                    this.showStatus = true;
                    this.statusType = "error";
                    this.statusMsg = err.error.feedback[0];
                    if (err.error.feedback[0]) {
                        this.selectedDate = [];
                    }
                },
                complete: () => { },
            })
    };

    /**
     * Method will set the list of selected dates array
     * @param string val
     * @returns {undefined}
     */
    setDateList(val: string) {
        var pos = this.selectedDate.indexOf(val);
        if (val === 'all') {
            this.selectedDate = [];
            this.uniqueEndDates.forEach((value: string) => {
                this.selectedDate.push(value);
            })
        } else if (pos === -1) {
            this.selectedDate.push(val);
        } else {
            this.selectedDate.splice(pos, 1);
        }
    };

    /**
    * Method will convert date format from "m-d-Y to Y-m-d"
    * @param array arrayData
    * @returns {Array}any
    */
    convertDateFormat(arrayData: string[]) {
        var tempArray: string[] = [];
        arrayData.forEach((value: string) => {
            var splitDate1 = value.split('-');
            var month = splitDate1[0];
            var day = splitDate1[1];
            var year = splitDate1[2];
            tempArray.push(year + "-" + month + "-" + day);
        })
        return tempArray;
    };

    /**
     * Method will validate the date
     * @param {string} date
     * @returns {undefined}
     */
    validDateMsg!: string;
    showvalidDateMsg!: boolean;
    validDate(date: any) {
        const newDate = new Date(date.srcElement.value);
        const year = newDate.getFullYear();
        const currentDate = new Date();
        if (date.srcElement.value !== '' && (year.toString().length > 4 || newDate < currentDate || isNaN(newDate.getTime()))) {
            this.validDateMsg = "Please provide valid date: (MM-DD-YYYY)";
            this.showvalidDateMsg = true;
            this.enableUpdateButton = false;
        } else {
            this.validDateMsg = '';
            this.showvalidDateMsg = false;
            this.enableUpdateButton = true;
        }
    };

    /**
     * TRX-7337 Method to export active products
     * exports csv file with active products list
     * @returns {undefined}
     */
    exportActiveProducts() {
        this.supplierProductData.searchData.action = "export";
        this.getActiveProductsSubscribe = this.supplierCatalogService.getActiveProducts(this.supplierProductData)
            .pipe(
                catchError((err) => {
                    this.showStatus = true;
                    this.statusType = "error";
                    if (err.error.feedback[0]) {
                        this.statusMsg = "Error while exporting products.";
                    }
                    return throwError(() => new Error('ups sommething happend'));
                })
            )
            .subscribe({
                next: (res: any) => {
                    var csvData = res.data.exportData;
                    this.exportFileService.exportFileByExtension("ActiveProducts", csvData, "csv", "text/csv");
                },
                error: (err: HttpErrorResponse) => {
                    this.showStatus = true;
                    this.statusType = "error";
                    if (err.error.feedback[0]) {
                        this.statusMsg = "Error while exporting products.";
                    }
                },
                complete: () => { },
            })
    };

    /**
    * Save edited details of a product.
    * @param {int} auctionId
    * @param {string} endTime
    * @param {Object} data
    * @returns {undefined}
    */
    editProductSubscribe!: Subscription;
    saveEditedProduct(auctionId: number, endTime: string, data: any) {
        this.editProductSubscribe = this.supplierCatalogService.editProduct(auctionId, endTime, data)
            .pipe(
                catchError((err) => {
                    if (err.error.feedback[0]) {
                        this.showStatus = true;
                        this.statusType = "error";
                        err.error.feedback.forEach((errorMessage: string) => {
                            this.statusMsg = errorMessage;
                        })
                    }
                    return throwError(() => new Error('ups sommething happend'));
                })
            )
            .subscribe({
                next: () => {
                    this.statusMsg = 'Product Updated Successfully';
                    this.statusType = "success";
                    this.showStatus = true;
                    this.searchActiveProducts('update');
                },
                error: (err: HttpErrorResponse) => {
                    if (err.error.feedback[0]) {
                        this.showStatus = true;
                        this.statusType = "error";
                        err.error.feedback.forEach((errorMessage: string) => {
                            this.statusMsg = errorMessage;
                        })
                    }
                },
                complete: () => { },
            })
    };

    deleteProductSubscribe!: Subscription;
    deleteProduct(auction_id: number) {
        this.deleteProductSubscribe = this.supplierCatalogService.deleteProduct(auction_id)
            .pipe(
                catchError((err) => {
                    if (err.error.feedback[0]) {
                        this.showStatus = true;
                        this.statusType = "error";
                        err.error.feedback.forEach((errorMessage: string) => {
                            this.statusMsg = errorMessage;
                        })
                    }
                    return throwError(() => new Error('ups sommething happend'));
                })
            )
            .subscribe({
                next: () => {
                    this.showStatus = true;
                    this.statusType = "success";
                    this.statusMsg = "Product Deleted Successfully";
                    if (!this.isLoading) {
                        this.isLoading = true;
                        this.searchActiveProducts('update');
                    }
                },
                error: (err: HttpErrorResponse) => {
                    if (err.error.feedback[0]) {
                        this.showStatus = true;
                        this.statusType = "error";
                        err.error.feedback.forEach((errorMessage: string) => {
                            this.statusMsg = errorMessage;
                        })
                    }
                },
                complete: () => { },
            })

    this.closeModal();
  }

  // Trackby function for track looping items
  trackByFn(index:number, item:any){
    return item
  }

    deleteProductModal!: NgbModalRef;
    openDeleteProductModal(auction_id: number) {
        this.deleteProductModal = this.modalService.open(this.deleteProductModalRef);
        this.auctionId = auction_id;
    }

    closeModal() {
        this.deleteProductModal.close();
    }

    dateFormat(date: string | Date, format: string = 'yyyy-MM-dd') {
        return date != "" ? formatDate(date, format, 'en') : date;
    }

    ngOnDestroy() {
        this.getActiveProductsSubscribe?.unsubscribe();
        this.updateActiveProductsSubscribe?.unsubscribe();
        this.editProductSubscribe?.unsubscribe();
    }

    /**
     * Save details of product being edited when edit icon is clicked on
     * product row.
     * @param productToEdit ActiveProductsInterface['data']['products'][0]
     * @returns void
     */
    onEditRowInit(productToEdit: ActiveProductsInterface['data']['products'][0]): void {
        this.productToEdit = { ...productToEdit };
    }

    /**
     * Detect changes done to product data on row edit and save the data.
     * @param productToSave ActiveProductsInterface['data']['products'][0]
     * @param index number
     * @returns void
     */
    onEditRowSave(productToSave: ActiveProductsInterface['data']['products'][0], index: number): void {
        this.showStatus = false;
        let error = false;
        if (productToSave.hasOwnProperty('item_expire_date_ts')) {
            productToSave.item_expire_date_ts = this.dateFormat(productToSave.item_expire_date_ts, 'yyyy/MM/dd');
        }
        let payload: any = this.utilities.diffHelper(productToSave, this.productToEdit);
        if (payload.hasOwnProperty('allocation_type') && payload.allocation_type === '') {
            delete payload.allocation_type;
        }
        Object.entries(payload).forEach(([key, value]) => {
            if (['item_expire_date_ts', 'end_date_ts', 'allocation_type'].indexOf(key) === -1 && (value === '' || value === null)) {
                this.errorField = key;
                error = true;
            }
        });
        //Save only when there are changes in data and no validation errors.
        if (Object.keys(payload).length > 0 && !error) {
            payload['end_time_ts'] = this.dateFormat(productToSave.end_time_ts, 'yyyy/MM/dd');
            if (payload.hasOwnProperty('allocation') && !payload.hasOwnProperty('allocation_type')) {
                this.ndcLevelAllocReqd = productToSave.ndc_level_alloc_enabled;
                this.allocNdc = productToSave.ndc;
                payload['allocation_type'] = productToSave.allocation_type;
            }
            if (this.ndcLevelAllocReqd === 1) {
                payload['ndc'] = this.allocNdc;
                payload['ndc_level_alloc_enabled'] = this.ndcLevelAllocReqd;
                if(!payload.hasOwnProperty('allocation')) {
                    payload['allocation'] = this.ndcAllocation;
                }
            }
            this.saveEditedProduct(productToSave.auction_id, payload.end_time_ts, payload);
        } else if (error){
            productToSave.item_expire_date_ts = new Date(productToSave.item_expire_date_ts);
            this.tableComponent.initRowEdit(productToSave);
        } else {
            this.activeProducts[index] = this.productToEdit;
        }
    }

    /**
     * Handle when row editing is cancelled and restore original data.
     * @param product ActiveProductsInterface['data']['products'][0]
     * @param index number
     * @returns void
     */
    onRowEditCancel(product: ActiveProductsInterface['data']['products'][0], index: number): void {
        this.activeProducts[index] = this.productToEdit;
    }

    /**
     * Method to display Same NDC Allocation confirmation Modal popup
    */
    allocationModal!: NgbModalRef;
    displayAllocationModal(auction_id: number, ndc: string, allocation: number) {
        this.resetAllocationVals();
        this.allocationModal = this.modalService.open(this.allocationModalRef);
        this.allocAuctionId = auction_id;
        this.allocNdc = ndc;
        this.ndcAllocation = allocation;
    }

    /**
     * Reset Allocation Modal popup Values
    */
    resetAllocationVals() {
        this.ndcLevelAllocReqd = 0;
        this.allocNdc = "";
        this.ndcAllocation = 0;
    }

    /**
     * Sets Allocation Flag
    */
    setAllocationFlag(ndc: string) {
        this.ndcLevelAllocReqd = 1;
        this.closeAllocationModal();
    }

    /**
     * Close the allocation Modal popup
    */
    closeAllocationModal() {
        this.allocationModal.close();
    }
}
