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

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

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

// Services
import { SessionService } from 'src/app/services/session/session.service';
import { AccountInfoService } from 'src/app/services/accountInfo/account-info.service';
import { LocalStorageService } from 'src/app/services/localstorage/local-storage.service';

import { StripePaymentModelComponent } from 'src/app/components/stripe-payment-model/stripe-payment-model.component';

import { ConfirmSkipPaymentModelComponent } from 'src/app/feature-modules/auth/components/confirm-skip-payment-model/confirm-skip-payment-model.component';

// Third Party
import { NgbModal, NgbModalConfig, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { environment } from 'src/environments/environment';

@Component({
  standalone: false,
  selector: 'payment',
  templateUrl: './payment.component.html',
  styleUrls: ['./payment.component.scss']
})
export class PaymentComponent implements AfterViewInit, OnDestroy {
    session!: SessionDataInterface['data'];
    isBuyer!: boolean;
    renderMe: boolean = false;
    regActiveStep: string = 'step4';
    imgUrl: string = environment.imageUrl;
    getAccountInfoSubscribe!: Subscription;
    payMethodAdded: boolean = false;
    paymentMethodsSubscribe!:Subscription;
    deaText: string = '';

    constructor(
      private router: Router,
      private accountInfoService: AccountInfoService,
      private sessionService: SessionService,
      private elementRef: ElementRef,
      private modalService: NgbModal,
      private ngbModalconfig: NgbModalConfig,
      private localStorageService: LocalStorageService,
    ) {
        this.ngbModalconfig.backdrop = 'static';
        this.ngbModalconfig.keyboard = false;
      }
      
    async ngAfterViewInit(): Promise<void> {}
    
    ngOnInit(): void {
        this.session = this.sessionService.getSession();
        this.isBuyer = this.session.is_buyer;
        this.renderMe = this.session.logged_in && this.session.reg_step === 5 && this.session.is_buyer;
        this.hasPayMethods();
        this.getUserSession();
    }
    
    /**
    * Get user session and return defer promise
    * @returns {.$q@call;defer.promise}
    */
    checkSession() {
        return new Promise((resolve) => {
            var r = this.sessionService.get();
            r.then(() => {
                this.session = this.sessionService.getSession();
                resolve(this.session);
            }).catch(err => {
                this.sessionService.errorCallBack(err);
            });
        })
    };
    
    /**
     * Check session and redirect the user if true
     * @returns {undefined}
     */
    getUserSession() {
        this.checkSession().then(() => {
            if (this.session.logged_in) {
                if (this.session.account_status === "final") {
                    this.router.navigate(['/market/home'])
                }
                if (this.session.account_status === "valid") {
                    this.router.navigate(['/market/accountVerify'])
                }
                if (this.session.account_status === 'new') {
                    this.router.navigate(['/market/storeInfo'])
                }
            } else {
                this.localStorageService.clear();
                this.router.navigate(['/market/login'])
            }
            this.deaText = 'DEA';
            if (this.session.is_hin === true) {
                this.deaText = 'HIN';
            }
        }).catch(err => {
            /**if your asynchronous function returns defer.reject()
             instead of defer.resolve() you can catch the error here**/
        })
    };
    
    hasPayMethodsSubscribe!:Subscription;
    hasPayMethods() {
        this.hasPayMethodsSubscribe = this.accountInfoService
            .hasPayMethods()
            .pipe(
                catchError(() => {
                  return throwError(() => new Error('ups sommething happend'));
                })
            )
            .subscribe({
                next: (res: any) => {
                  if (res.data !== false) {
                    this.payMethodAdded = true;
                  }
                },
                error: (err: HttpErrorResponse) => {
                  this.accountInfoService.errorCallBack(err);
                },
                complete: () => { }
            });
    };

    /**
     * Opens the Stripe payment modal for setting up a payment method.
     * Subscribes to the addPayMethodStatus event to update the payment method status.
     */
    stripePaymentModel!: NgbModalRef
    showStripePaymentModel() {
        this.paymentMethodsSubscribe = this.accountInfoService
        .getAllPaymentMethods()
        .subscribe({
            next: (res: any) => {
                if (res.data !== false) {
                  this.stripePaymentModel = this.modalService.open(StripePaymentModelComponent,{size: 'sm'});
                  this.stripePaymentModel.componentInstance.stripePaymentModel = this.stripePaymentModel;
                  this.stripePaymentModel.componentInstance.stripePaymentModelNo = this.stripePaymentModelNo;
                  this.stripePaymentModel.componentInstance.paymentMethodCards = res.data.cards;
                  this.stripePaymentModel.componentInstance.paymentMethodBank = res.data.bankAccounts;
                  this.stripePaymentModel.componentInstance.pendingBankPymentMethods = res.data?.pendingBankPayMethods || [];

                  // Subscribe to addPayMethodStatus event
                  this.stripePaymentModel.componentInstance.addPayMethodStatus.subscribe((data: any) => {
                      if (data.status) {
                        this.payMethodAdded = data.status;
                      }
                  });
                }
            },
            error: (err: HttpErrorResponse) => {
              this.accountInfoService.errorCallBack(err);
            },
            complete: () => { }
        });
    };
    
    /**
     * Dismisses the Stripe payment modal.
     * @param action
     */
    stripePaymentModelNo(action: any) {
        this.stripePaymentModel.dismiss();
    };
  
    /**
     * Saves the payment step information for the user.
     * On success, refreshes the session and navigates to the license verification page.
     * Handles errors using the accountInfoService error callback.
     */
    saveUserInfoSubscribe!:Subscription;
    savePaymentStep() {
        let paymentStepInfo = {
          'xu_payment_step': 1,
          'auto_validate': this.localStorageService.getItem('autoValidate')
        };
        this.saveUserInfoSubscribe = this.accountInfoService.saveUserInfo(paymentStepInfo)
        .pipe(
          catchError(() => {
            return throwError(() => new Error('ups sommething happend'));
          })
        ).subscribe({
          next: () => {
            this.sessionService.reCheckSession();
            if (this.localStorageService.getItem('autoValidate') === 'true') {
                this.router.navigate(['/market/home']);
            } else {
                this.router.navigate(['/market/licenseVerification']);
            }
            
          },
          error: (err: HttpErrorResponse) => {
            this.accountInfoService.errorCallBack(err);
          },
          complete: () => { }
        });
    };

    /**
     * Opens the skip or confirm modal for payment step.
     */
    confirmSkipPaymentModel!: NgbModalRef
    skipPaymentModel() {
        this.confirmSkipPaymentModel = this.modalService.open(ConfirmSkipPaymentModelComponent,{size: 'sm'});
        this.confirmSkipPaymentModel.componentInstance.confirmSkipPaymentModel = this.confirmSkipPaymentModel
        this.confirmSkipPaymentModel.componentInstance.confirmSkipPaymentModelNo = this.confirmSkipPaymentModelNo
    };
    
    /**
     * Dismisses the confirm modal.
     * @param action
     */
    confirmSkipPaymentModelNo(action: any) {
        this.confirmSkipPaymentModel.dismiss();
    };
    
    ngOnDestroy(): void {
        this.saveUserInfoSubscribe?.unsubscribe();
        this.hasPayMethodsSubscribe?.unsubscribe();
        this.paymentMethodsSubscribe?.unsubscribe();
    }
}
