import { CommonModule } from '@angular/common';
import { Component, ElementRef, inject, viewChild } from '@angular/core';
import {
  FormArray,
  FormBuilder,
  FormControl,
  FormGroup,
  ReactiveFormsModule,
  Validators,
} from '@angular/forms';

import { TranslateModule } from '@ngx-translate/core';
import { Store } from '@ngxs/store';
import { Select2Data, Select2Module, Select2UpdateEvent } from 'ng-select2-component';
import { Observable, map, of } from 'rxjs';

import { AddressBlock } from './address-block/address-block';
import { DeliveryBlock } from './delivery-block/delivery-block';
import { PaymentBlock } from './payment-block/payment-block';
import { ClearCartAction } from '../../../shared/action/cart.action';
import { CheckoutAction, PlaceOrderAction } from '../../../shared/action/order.action';
import { GetSettingOptionAction } from '../../../shared/action/setting.action';
import { Breadcrumb } from '../../../shared/components/widgets/breadcrumb/breadcrumb';
import { Button } from '../../../shared/components/widgets/button/button';
import { Loader } from '../../../shared/components/widgets/loader/loader';
import { AddressModal } from '../../../shared/components/widgets/modal/address-modal/address-modal';
import { NoData } from '../../../shared/components/widgets/no-data/no-data';
import * as data from '../../../shared/data/country-code';
import { IAccountUser } from '../../../shared/interface/account.interface';
import { IBreadcrumb } from '../../../shared/interface/breadcrumb';
import { ICart } from '../../../shared/interface/cart.interface';
import { IOrderCheckout } from '../../../shared/interface/order.interface';
import { IDeliveryBlock, IValues } from '../../../shared/interface/setting.interface';
import { CurrencySymbolPipe } from '../../../shared/pipe/currency-symbol.pipe';
import { CartService } from '../../../shared/services/cart.service';
import { AccountState } from '../../../shared/state/account.state';
import { AuthState } from '../../../shared/state/auth.state';
import { CartState } from '../../../shared/state/cart.state';
import { CountryState } from '../../../shared/state/country.state';
import { OrderState } from '../../../shared/state/order.state';
import { SettingState } from '../../../shared/state/setting.state';
import { StateState } from '../../../shared/state/state.state';

@Component({
  selector: 'app-checkout',
  imports: [
    CommonModule,
    TranslateModule,
    ReactiveFormsModule,
    Select2Module,
    CurrencySymbolPipe,
    Breadcrumb,
    Button,
    DeliveryBlock,
    PaymentBlock,
    AddressBlock,
    NoData,
    Loader,
    AddressModal,
  ],
  templateUrl: './checkout.html',
  styleUrl: './checkout.scss',
})
export class Checkout {
  private store = inject(Store);
  private formBuilder = inject(FormBuilder);
  public cartService = inject(CartService);

  public breadcrumb: IBreadcrumb = {
    title: 'Checkout',
    items: [{ label: 'Checkout', active: true }],
  };

  user$: Observable<IAccountUser> = inject(Store).select(
    AccountState.user,
  ) as Observable<IAccountUser>;
  accessToken$: Observable<String> = inject(Store).select(
    AuthState.accessToken,
  ) as Observable<String>;
  cartItem$: Observable<ICart[]> = inject(Store).select(CartState.cartItems);
  checkout$: Observable<IOrderCheckout> = inject(Store).select(
    OrderState.checkout,
  ) as Observable<IOrderCheckout>;
  setting$: Observable<IValues> = inject(Store).select(SettingState.setting) as Observable<IValues>;
  cartDigital$: Observable<boolean | number> = inject(Store).select(
    CartState.cartHasDigital,
  ) as Observable<boolean | number>;
  countries$: Observable<Select2Data> = inject(Store).select(CountryState.countries);

  readonly AddressModal = viewChild<AddressModal>('addressModal');
  readonly cpnRef = viewChild<ElementRef<HTMLInputElement>>('cpn');

  public form: FormGroup;
  public coupon: boolean = true;
  public couponCode: string;
  public appliedCoupon: boolean = false;
  public couponError: string | null;
  public checkoutTotal: IOrderCheckout;
  public loading: boolean = false;

  public shippingStates$: Observable<Select2Data>;
  public billingStates$: Observable<Select2Data>;
  public codes = data.countryCodes;

  constructor() {
    this.store.dispatch(new GetSettingOptionAction());

    this.form = this.formBuilder.group({
      products: this.formBuilder.array([], [Validators.required]),
      shipping_address_id: new FormControl('', [Validators.required]),
      billing_address_id: new FormControl('', [Validators.required]),
      points_amount: new FormControl(false),
      wallet_balance: new FormControl(false),
      coupon: new FormControl(),
      delivery_description: new FormControl('', [Validators.required]),
      delivery_interval: new FormControl(),
      payment_method: new FormControl('', [Validators.required]),
      create_account: new FormControl(false),
      name: new FormControl('', [Validators.required]),
      email: new FormControl('', [Validators.required, Validators.email]),
      country_code: new FormControl('91', [Validators.required]),
      phone: new FormControl('', [Validators.required]),
      password: new FormControl(),
      shipping_address: new FormGroup({
        title: new FormControl('', [Validators.required]),
        street: new FormControl('', [Validators.required]),
        city: new FormControl('', [Validators.required]),
        phone: new FormControl('', [Validators.required]),
        pincode: new FormControl('', [Validators.required]),
        country_code: new FormControl('91', [Validators.required]),
        country_id: new FormControl('', [Validators.required]),
        state_id: new FormControl('', [Validators.required]),
      }),
      billing_address: new FormGroup({
        same_shipping: new FormControl(false),
        title: new FormControl('', [Validators.required]),
        street: new FormControl('', [Validators.required]),
        city: new FormControl('', [Validators.required]),
        phone: new FormControl('', [Validators.required]),
        pincode: new FormControl('', [Validators.required]),
        country_code: new FormControl('91', [Validators.required]),
        country_id: new FormControl('', [Validators.required]),
        state_id: new FormControl('', [Validators.required]),
      }),
    });

    this.store.selectSnapshot(state => state.setting).setting.activation.guest_checkout = true;

    if (this.store.selectSnapshot(state => state.auth && state.auth.access_token)) {
      this.form.removeControl('create_account');
      this.form.removeControl('name');
      this.form.removeControl('email');
      this.form.removeControl('country_code');
      this.form.removeControl('phone');
      this.form.removeControl('password');
      this.form.removeControl('password_confirmation');
      this.form.removeControl('shipping_address');
      this.form.removeControl('billing_address');

      this.cartDigital$.subscribe(value => {
        if (value == 1) {
          this.form.controls['shipping_address_id'].clearValidators();
          this.form.controls['delivery_description'].clearValidators();
        } else {
          this.form.controls['shipping_address_id'].setValidators([Validators.required]);
          this.form.controls['delivery_description'].setValidators([Validators.required]);
        }
        this.form.controls['shipping_address_id'].updateValueAndValidity();
        this.form.controls['delivery_description'].updateValueAndValidity();
      });
    } else {
      if (this.store.selectSnapshot(state => state.setting).setting.activation.guest_checkout) {
        this.form.removeControl('shipping_address_id');
        this.form.removeControl('billing_address_id');
        this.form.removeControl('points_amount');
        this.form.removeControl('wallet_balance');

        this.form.controls['create_account'].valueChanges.subscribe(value => {
          if (value) {
            this.form.controls['name'].setValidators([Validators.required]);
            this.form.controls['password'].setValidators([Validators.required]);
          } else {
            this.form.controls['name'].clearValidators();
            this.form.controls['password'].clearValidators();
          }
          this.form.controls['name'].updateValueAndValidity();
          this.form.controls['password'].updateValueAndValidity();
        });

        this.form.statusChanges.subscribe(value => {
          if (value == 'VALID') {
            this.checkout();
          }
        });
      }
    }

    this.form.get('billing_address.same_shipping')?.valueChanges.subscribe(value => {
      if (value) {
        this.form
          .get('billing_address.title')
          ?.setValue(this.form.get('shipping_address.title')?.value);
        this.form
          .get('billing_address.street')
          ?.setValue(this.form.get('shipping_address.street')?.value);
        this.form
          .get('billing_address.country_id')
          ?.setValue(this.form.get('shipping_address.country_id')?.value);
        this.form
          .get('billing_address.state_id')
          ?.setValue(this.form.get('shipping_address.state_id')?.value);
        this.form
          .get('billing_address.city')
          ?.setValue(this.form.get('shipping_address.city')?.value);
        this.form
          .get('billing_address.pincode')
          ?.setValue(this.form.get('shipping_address.pincode')?.value);
        this.form
          .get('billing_address.country_code')
          ?.setValue(this.form.get('shipping_address.country_code')?.value);
        this.form
          .get('billing_address.phone')
          ?.setValue(this.form.get('shipping_address.phone')?.value);
      } else {
        this.form.get('billing_address.title')?.setValue('');
        this.form.get('billing_address.street')?.setValue('');
        this.form.get('billing_address.country_id')?.setValue('');
        this.form.get('billing_address.state_id')?.setValue('');
        this.form.get('billing_address.city')?.setValue('');
        this.form.get('billing_address.pincode')?.setValue('');
        this.form.get('billing_address.country_code')?.setValue('');
        this.form.get('billing_address.phone')?.setValue('');
      }
    });

    this.cartService.getUpdateQtyClickEvent().subscribe(() => {
      this.products();
      this.checkout();
    });
  }

  get productControl(): FormArray {
    return this.form.get('products') as FormArray;
  }

  ngOnInit() {
    this.checkout$.subscribe(data => (this.checkoutTotal = data));
    this.products();
  }

  products() {
    this.cartItem$.subscribe(items => {
      this.productControl.clear();
      items.forEach((item: ICart) =>
        this.productControl.push(
          this.formBuilder.group({
            product_id: new FormControl(item?.product_id, [Validators.required]),
            variation_id: new FormControl(item?.variation_id ? item?.variation_id : ''),
            quantity: new FormControl(item?.quantity),
          }),
        ),
      );
    });
  }

  selectShippingAddress(id: number) {
    if (id) {
      this.form.controls['shipping_address_id'].setValue(Number(id));
      this.checkout();
    }
  }

  selectBillingAddress(id: number) {
    if (id) {
      this.form.controls['billing_address_id'].setValue(Number(id));
      this.checkout();
    }
  }

  selectDelivery(value: IDeliveryBlock) {
    this.form.controls['delivery_description'].setValue(value?.delivery_description);
    this.form.controls['delivery_interval'].setValue(value?.delivery_interval);
    this.checkout();
  }

  selectPaymentMethod(value: string) {
    this.form.controls['payment_method'].setValue(value);
    this.checkout();
  }

  togglePoint(event: Event) {
    this.form.controls['points_amount'].setValue((<HTMLInputElement>event.target)?.checked);
    this.checkout();
  }

  toggleWallet(event: Event) {
    this.form.controls['wallet_balance'].setValue((<HTMLInputElement>event.target)?.checked);
    this.checkout();
  }

  showCoupon() {
    this.coupon = true;
  }

  setCoupon(value?: string) {
    this.couponError = null;

    if (value) this.form.controls['coupon'].setValue(value);
    else this.form.controls['coupon'].reset();

    this.store.dispatch(new CheckoutAction(this.form.value)).subscribe({
      error: err => {
        this.couponError = err.message;
      },
      complete: () => {
        this.appliedCoupon = value ? true : false;
        this.couponError = null;
      },
    });
  }

  couponRemove() {
    this.setCoupon();
  }

  shippingCountryChange(data: Select2UpdateEvent) {
    if (data && data?.value) {
      this.shippingStates$ = this.store
        .select(StateState.states)
        .pipe(map(filterFn => filterFn(+data?.value)));
    } else {
      this.form.get('shipping_address.state_id')?.setValue('');
      this.shippingStates$ = of();
    }
  }

  billingCountryChange(data: Select2UpdateEvent) {
    if (data && data?.value) {
      this.billingStates$ = this.store
        .select(StateState.states)
        .pipe(map(filterFn => filterFn(+data?.value)));
      if (this.form.get('billing_address.same_shipping')?.value) {
        setTimeout(() => {
          this.form
            .get('billing_address.state_id')
            ?.setValue(this.form.get('shipping_address.state_id')?.value);
        }, 200);
      }
    } else {
      this.form.get('billing_address.state_id')?.setValue('');
      this.billingStates$ = of();
    }
  }

  checkout() {
    // If has coupon error while checkout
    if (this.couponError) {
      this.couponError = null;
      this.cpnRef()!.nativeElement.value = '';
      this.form.controls['coupon'].reset();
    }

    if (this.form.valid) {
      this.loading = true;
      this.store.dispatch(new CheckoutAction(this.form.value)).subscribe({
        error: err => {
          this.loading = false;
          throw new Error(err);
        },
        complete: () => {
          this.loading = false;
        },
      });
    } else {
      Object?.keys(this.form?.controls).filter(key => this.form.controls[key].invalid);
    }
  }

  placeorder() {
    if (this.form.valid) {
      const cpnRef = this.cpnRef();
      if (cpnRef && !cpnRef.nativeElement.value) {
        this.form.controls['coupon'].reset();
      }
      this.store.dispatch(new PlaceOrderAction(this.form.value));
    }
  }

  clearCart() {
    this.store.dispatch(new ClearCartAction());
  }

  ngOnDestroy() {
    this.form.reset();
  }
}
