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

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

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

// Services
import { SessionService } from 'src/app/services/session/session.service';
import { OrdersService } from 'src/app/services/orders/orders.service';
import { ExportFileService } from 'src/app/feature-modules/auth/services/exportFile/export-file.service';
import { ManagePurchaseService } from '../services/manage-purchase.service';
import { UtilitiesService } from 'src/app/services/utilities/utilities.service';

// Interfaces
import { SessionDataInterface } from 'src/app/interfaces/session-data-interface';
import { SearchData, getStatusListInterface} from 'src/app/interfaces/common-interfaces'
import { userManagePurchaseInterface } from 'src/app/interfaces/user/user-managePurchases-interface';
import { NgbDate, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
import { DataTransmitterService } from 'src/app/services/dataTransmitter/data-transmitter.service';

interface UrlParams {
  orders: string,
  pageNumber: number
}

interface Pager {
  totalItems: number,
  currentPage: number,
  pageSize: number,
  totalPages: number,
  startPage: number,
  endPage: number,
  startIndex: number,
  endIndex: number,
  pages: number[]
}

interface orderStatus {
  code: number | string, 
  status: string
}

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

  session!: SessionDataInterface['data'];
  renderMe!: boolean;
  isUserAllowed!:boolean;
  order!:string | null;
  pageNumber!:number | null;

  /*
  * Store passed url params
  * @type Object
  */
  urlParams:UrlParams = {
    orders: '',
    pageNumber: 1
  };

  /**
  * variable to unsubscribe from all observable subscriptions
  */
  getUserPurchasesDataSubscription!: Subscription;
  getStatusListSubscription!: Subscription;

  /**
  * variable to bind loader
  */
  isloading:boolean = true;

  /**
  * Store value if response is empty
  */
  isempty:boolean = false;

  exportErrorMessage!:string;
  exportErrorVisible!:boolean;

  exportSuccessMessage!:string;
  exportSuccessVisible!:boolean;

  exportInformaton!:string;
  exportInformatonVisible!:boolean;

  statusMsg!: string;
  showMsg!: boolean;
  statusType!: string;


  /**
   * Store active tab Info
   */
  activeTab:string = '';

  /**
   * Store multi pagination Data
   */
  pager: Pager = {
    totalItems: 0,
    currentPage: 1,
    pageSize: 0,
    totalPages: 0,
    startPage: 0,
    endPage: 0,
    startIndex: 0,
    endIndex: 0,
    pages: [] as number[]
  };

  fromDateStruct!: NgbDateStruct;
  toDateStruct!: NgbDateStruct;
  today: NgbDateStruct = {
    year: new Date().getFullYear(),
    month: new Date().getMonth() + 1,
    day: new Date().getDate()
  }
  
  /**
   * Search Form Visible
   */
  searchVisible:boolean = true;

  /**
   * Order status dropdown
   */
  orderStatus: orderStatus[] = [
      {code: "All", status: "All"}
  ];

  /**
   * Payment status dropdown
   */
  paymentStatusArray: string[] = ["All", "Paid", "Scheduled", "Due", "Processing", "Failed"];

  /**
  * Order Search Params
  */
  searchData: SearchData = {
    fromDate: "",
    toDate : "",
    ndc : "",
    orderId : "",
    winnerId : "",
    status : "All",
    paymentStatus : "All",
    supplierName : "",
    productName : ""
  };

  purchasesData: userManagePurchaseInterface['data']['purchase_result'] = [];
  totalItems:number = 0;

  constructor(
    private sessionService : SessionService,
    private orders : OrdersService,
    private exportFile: ExportFileService,
    private activatedRoute: ActivatedRoute,
    private router: Router,
    private stripNDCPipe: StripNDCPipe,
    private managePurchaseService: ManagePurchaseService,
    private utilities: UtilitiesService,
    private dataTransmitter: DataTransmitterService
  ) { }

  ngOnInit(): void {
    this.session = this.sessionService.getSession();
    this.renderMe = this.session.logged_in && (this.session.reg_step > 6) && this.session.is_buyer;
    this.order = this.activatedRoute.snapshot.queryParams['orders'];
    this.pageNumber = this.activatedRoute.snapshot.queryParams['pageNumber'];
    this.updateManagePurchasesListener = this.managePurchaseService.updateManagePurchases.subscribe({
        next: () => {
            this.searchData.ndc = this.stripNDCPipe.transform(this.searchData.ndc);
            this.managePurchasesData(this.urlParams.orders, this.urlParams.pageNumber, this.searchData)
        }
    });
    /*
    * Introduced below condition as per TRX-7634.
    * If the isUserAllowed false, the logged-in user is considered to be an admin-level 8 user.
    * If the isUserAllowed true, the logged-in user is considered to be not an admin-level 8 user.
    */
    if (this.session.is_admin_restricted) {
      this.isUserAllowed = false;
    } else {
      this.isUserAllowed = true;
    }
    this.prepareOrderStatus();
    if (this.order)
    {
        this.urlParams.orders = this.order;
    }
    if (this.pageNumber)
    {
        this.urlParams.pageNumber = this.pageNumber;
    }
    this.searchData.ndc = this.stripNDCPipe.transform(this.searchData.ndc);
    this.managePurchasesData(this.urlParams.orders, this.urlParams.pageNumber, this.searchData);
    this.dataTransmitter.lane4AdData.next({ndc: '', pageName: 'ManagePurchases'});
    }

  /**
  * Get order status list and added to order status dropdown
  * @returns {undefined}
  */
  prepareOrderStatus() {
    this.getStatusListSubscription = this.orders.getStatusList()
    .pipe(
      catchError(() => {
        return throwError(() => new Error('ups sommething happend'));
      })
    )
    .subscribe({
      next: (res: getStatusListInterface) => {
          var temp = res.data;
          var processed:number[] = [];
          temp.forEach((value:getStatusListInterface['data'][0], key:number) => {
            if ([2,4,5,24,25].indexOf(value.id) > -1) {
              processed.push(value.id);
            } else {
                this.orderStatus.push({code: value.id, status: value.status});
            }
          }),
          this.orderStatus.splice(3, 0, { code: processed.join(), status: "Processed" });
      },
      error: (err) => {
        this.orders.errorCallBack(err);
      },
      complete: () => { },
    })
  };

  /**
   * Set From Date and format to show in calendar text field
   * @param date
   */
  setFromDate(date: NgbDate) {
    this.searchData.fromDate = date.year+'-'+date.month+'-'+date.day;
  };

  /**
   * Set to date.
   * @param date 
   */
  setToDate(date: NgbDate) {
    this.searchData.toDate = date.year+'-'+date.month+'-'+date.day;
  };
  
  /**
   * sets From Date and To Date when entered manually.
   * @param date
   * @param field
   */
   manualDate(date: any, field: string) {
     var data = this.utilities.validateManualDate(date);
     if (data.valid) {
       var ngbDate = data.ngbDate;
       if (field === 'fromDate') {
         this.setFromDate(ngbDate);
       } else {
           this.setToDate(ngbDate);
       }
       this.validateSearchTimeframe();
     }
   }

  /**
  * Search orders using searchData
  * Send inclusive date range
  * @returns {undefined}
  */
  searchOrders (type: string) {
    this.searchData.ndc = this.stripNDCPipe.transform(this.searchData.ndc);
    this.urlParams.orders = 'search';
    this.router.navigate(['/market/managePurchases'], { queryParams: { orders: this.urlParams.orders, pageNumber: 1 } })
    if(type === 'search') {
        this.isloading = true;
        this.managePurchasesData('search', 1, this.searchData);
    }
    if(type === 'export') {
        this.exportErrorMessage ='';
        this.exportErrorVisible = false;
        this.exportSuccessMessage ='';
        this.exportSuccessVisible = false;
        this.statusMsg = '';
        this.showMsg = false;
        /**
         * As per TRX-7340, applying search filter on 
         * Manage Purhcases Export functionality.
         *
         *  var exportData = {
         *       fromDate: this.searchData.fromDate,
         *       toDate : this.searchData.toDate,
         *      status : this.searchData.status
         *  };
         *
         *  The above exportData replaced with this.searchData
         *
         */
        this.getUserPurchasesDataSubscription = this.orders.getUserPurchasesData(type, 1, this.searchData)
        .pipe(
          catchError((err) => {
            var err_feedback = err.error.feedback
            if(err_feedback) {
              for (let errorMessage of err_feedback){
                this.exportErrorMessage += errorMessage;
                this.exportErrorVisible = true;
                this.statusMsg += errorMessage;
                this.showMsg = true;
                this.statusType = 'error';
              }
            }
            
            return throwError(() => new Error('ups sommething happend'));
          })
        )
        .subscribe({
          next: (res: any) => {
            var csvData = res.data.export_data;
            this.showMsg = true;
            this.statusType = 'success';
            if (csvData) {
              this.exportSuccessMessage = "Success! Your file will begin downloading now.";
              this.statusMsg = "Success! Your file will begin downloading now.";
              this.exportSuccessVisible = true;
              this.exportFile.exportFileByExtension("Transaction History Report ", csvData, "csv", "text/csv");
            } else{
              this.exportErrorMessage += "There are no order records on file based on user's search criteria.";
              this.exportErrorVisible = true;
              this.statusMsg += "There are no order records on file based on user's search criteria.";
            }
          },
          error: (err: HttpErrorResponse) => {
            this.orders.errorCallBack(err);
          }
        })
    }
  };

  /**
  * Gives the purchases Data for a user
  * @param {string} ordersType
  * @param {int} pageNumber
  * @param {object} searchParam
  * @returns {promise}
  */
  managePurchasesData (ordersType:string, pageNumber:number, searchParam:SearchData) {
    this.purchasesData = [];
    this.totalItems = 0;
    this.pager.totalPages = 0;
    this.pager.currentPage = 0;
    this.isloading = true;
    this.urlParams.orders = ordersType;
    this.getUserPurchasesDataSubscription = this.orders.getUserPurchasesData(ordersType, pageNumber, searchParam)
      .pipe(
        catchError(() => {
          this.isempty = true;
          this.isloading = false;
          return throwError(() => new Error('ups sommething happend'));
        })
      )
      .subscribe({
        next: (res: userManagePurchaseInterface) => {
          this.purchasesData = res.data?.purchase_result;
          this.totalItems = res.data?.total_results;
          this.pager.totalPages = Math.ceil(this.totalItems / 100);
          this.pager.currentPage = pageNumber;
          this.pager = this.GetPager(this.pager.currentPage, 100);
          this.isloading = false;
          if(ordersType === 'search') {
              ordersType = 'all';
          }
          this.activeTab = ordersType;
          if(res.data?.purchase_result?.length === 0 || res.data?.purchase_result === undefined) {
              this.isempty = true;
          } else {
              this.isempty = false;
          }
          },
        error: (err: HttpErrorResponse) => {
          this.orders.errorCallBack(err);
          this.isempty = true;
          this.isloading = false;
        },
        complete: () => { },
      })
      return new Promise((resolve) => {
        resolve("");
      })
  }

  /**
  * Method to get pagination range
  * @returns {undefined}
  */
  GetPager(currentPage:number, pageSize:number) {
    // default to first page
    currentPage = currentPage || 1;

    // default page size is 10
    pageSize = pageSize || 10;

    // calculate total pages
    var totalPages:number = Math.ceil(this.totalItems / pageSize);

    var startPage:number, endPage:number;
    if (totalPages <= 10) {
        // less than 10 total pages so show all
        startPage = 1;
        endPage = totalPages;
    } else {
        // more than 10 total pages so calculate start and end pages
        if (currentPage <= 6) {
            startPage = 1;
            endPage = 10;
        } else if (currentPage + 4 >= totalPages) {
            startPage = totalPages - 9;
            endPage = totalPages;
        } else {
            startPage = currentPage - 5;
            endPage = currentPage + 4;
        }
    }

    // calculate start and end item indexes
    var startIndex:number = (currentPage - 1) * pageSize;
    var endIndex:number = Math.min(startIndex + pageSize - 1, this.totalItems - 1);
    const arrayRange = function (start:number, end:number) {
      return Array.from({ length: end - start }, function (v, k) {
        return k + start;
      });
    };

    // create an array of pages to ng-repeat in the pager control
    var pages:number[] = arrayRange(startPage, endPage+1);

    // return object with all pager properties required by the view
    return {
        totalItems: this.totalItems,
        currentPage: currentPage,
        pageSize: pageSize,
        totalPages: totalPages,
        startPage: startPage,
        endPage: endPage,
        startIndex: startIndex,
        endIndex: endIndex,
        pages: pages
    };
  };

  /**
  * Method to set page
  * @returns {undefined}
  */
  setPage (pageNumber:number) {
    this.pager.currentPage = pageNumber;
    if(this.urlParams.orders !== 'search') {
      this.router.navigate(['/market/managePurchases'], { queryParams: { orders: this.urlParams.orders, pageNumber: pageNumber } });
    } else {
      this.router.navigate(['/market/managePurchases'], { queryParams: { orders: this.urlParams.orders, pageNumber: pageNumber } });
      this.searchData.ndc = this.stripNDCPipe.transform(this.searchData.ndc);
    }
    this.managePurchasesData(this.urlParams.orders, pageNumber, this.searchData);
  };

  getNumber(number: number){
    return Number(number);
  }

  /**
  * Listener to update Manage Purchases
  */
  updateManagePurchasesListener!: Subscription;

  /**
   * clear Export Messages
   * @returns {undefined}
   */
  clearPreviousValues() {
      this.searchVisible = !this.searchVisible;
      this.exportErrorMessage ='';
      this.exportErrorVisible = false;
      this.exportSuccessMessage ='';
      this.exportSuccessVisible = false;
      this.statusMsg = '';
      this.showMsg = false;
  };

  /**
  * validate search timeframe for search
  */
  disableBtn: boolean = false;
  validateSearchTimeframe () {
    var fromDate:Date = this.searchData.fromDate != "" ? new Date(formatDate(this.searchData.fromDate, 'YYYY/MM/dd 00:00:00', 'en' )) : new Date(this.searchData.fromDate);
    var toDate:Date = this.searchData.toDate != "" ? new Date(formatDate(this.searchData.toDate, 'YYYY/MM/dd 23:59:59', 'en' )) : new Date(this.searchData.toDate);
    const twoYearsLater = new Date(fromDate);
    twoYearsLater.setFullYear(fromDate.getFullYear() + 2);
    this.exportInformaton = '';
    this.exportInformatonVisible = false;
    this.showMsg = false;
    this.disableBtn = false;
    if (toDate > twoYearsLater) {
      this.exportInformaton = "For greater than two year date range, please use the Export Report button.";
      this.statusMsg = "For greater than two year date range, please use the Export Report button.";
      this.exportInformatonVisible = true;
      this.showMsg = true;
      this.statusType = 'success';
      this.disableBtn = true
    }
  };

  setDateFormat(format: string) {
    this.utilities.dateFormat = format;
  }
  
  ngOnDestroy() {
    this.getStatusListSubscription?.unsubscribe();
    this.getUserPurchasesDataSubscription?.unsubscribe();
    this.updateManagePurchasesListener?.unsubscribe();
  }

}
