import { inject, Injectable } from '@angular/core';
import {
  ActivatedRouteSnapshot,
  Params,
  Router,
  RouterStateSnapshot,
} from '@angular/router';
import { DomainCheckoutService } from '@domain/checkout';
import { CustomerCreateFormData, decodeFormData } from '../create-customer';
import { CustomerCreateNavigation } from '@shared/services/navigation';
@Injectable({ providedIn: 'root' })
export class CustomerCreateGuard {
  private router = inject(Router);
  private checkoutService = inject(DomainCheckoutService);
  private customerCreateNavigation = inject(CustomerCreateNavigation);

  async canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot,
  ): Promise<boolean> {
    // exit with true if canActivateChild will be called
    if (route.firstChild) {
      return true;
    }

    let customerType = 'store';

    const processId = this.getProcessId(route);
    const formData = this.getFormData(route);
    const canActivateCustomerType = await this.setableCustomerTypes(
      processId,
      formData,
    );

    if (canActivateCustomerType[customerType] !== true) {
      customerType = Object.keys(canActivateCustomerType).find(
        (key) => canActivateCustomerType[key],
      );
    }

    await this.navigate(processId, customerType, route.queryParams);

    return true;
  }

  async canActivateChild(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot,
  ): Promise<boolean> {
    const processId = this.getProcessId(route);
    const customerType = route.routeConfig.path
      ?.replace('create/', '')
      ?.replace('/update', '');

    if (customerType === 'create-customer-main') {
      return true;
    }

    const formData = this.getFormData(route);

    const canActivateCustomerType = await this.setableCustomerTypes(
      processId,
      formData,
    );

    if (canActivateCustomerType[customerType]) {
      return true;
    }

    const activatableCustomerType = Object.keys(canActivateCustomerType)?.find(
      (key) => canActivateCustomerType[key],
    );

    await this.navigate(processId, activatableCustomerType, route.queryParams);

    return false;
  }

  async setableCustomerTypes(
    processId: number,
    formData: CustomerCreateFormData,
  ): Promise<Record<string, boolean>> {
    const res = await this.checkoutService
      .getSetableCustomerTypes(processId)
      .toPromise();

    // if (res.store) {
    //   res['store-p4m'] = true;
    // }

    // if (res.webshop) {
    //   res['webshop-p4m'] = true;
    // }

    if (formData?._meta) {
      const customerType = formData._meta.customerType;
      const hasLocalityCard = formData._meta.hasLocalityCard;

      if (customerType === 'store' && hasLocalityCard) {
        res.store = false;
        res['store-p4m'] = false;
        res.guest = false;
        res.b2b = false;
      }

      if (customerType === 'webshop' && hasLocalityCard) {
        res.webshop = false;
        res['webshop-p4m'] = false;
        res.store = false;
        res['store-p4m'] = false;
        res.guest = false;
        res.b2b = false;
      }
    }

    return res;
  }

  getProcessId(snapshot: ActivatedRouteSnapshot): number | undefined {
    if (snapshot.params['processId']) {
      return +snapshot.params['processId'];
    } else if (snapshot.parent) {
      return this.getProcessId(snapshot.parent);
    }
    return undefined;
  }

  getFormData(snapshot: ActivatedRouteSnapshot): CustomerCreateFormData {
    const formData = snapshot.queryParams['formData'];

    if (formData) {
      return decodeFormData(formData);
    }

    return {};
  }

  navigate(
    processId: number,
    customerType: string,
    queryParams: Params,
  ): Promise<boolean> {
    const path = this.customerCreateNavigation.createCustomerRoute({
      customerType,
      processId,
    });

    return this.router.navigate(path.path, {
      queryParams,
      queryParamsHandling: 'merge',
    });
  }
}
