import { NumberInput, coerceNumberProperty } from '@angular/cdk/coercion';
import { Injectable } from '@angular/core';
import { Router, UrlTree } from '@angular/router';
import { Filter } from '@shared/components/filter';
import { CustomerDTO, CustomerInfoDTO } from '@generated/swagger/crm-api';
import { NavigationRoute } from './defs/navigation-route';

@Injectable({ providedIn: 'root' })
export class CustomerSearchNavigation {
  constructor(private _router: Router) {}

  defaultRoute(params: { processId?: NumberInput }): NavigationRoute {
    const path = [
      '/kunde',
      params.processId ? coerceNumberProperty(params.processId) : undefined,
      'customer',
      { outlets: { primary: 'search', side: 'search-customer-main' } },
    ].filter((v) => !!v);

    const urlTree = this._router.createUrlTree(path, { queryParams: {} });

    return {
      path,
      urlTree,
      queryParams: {},
    };
  }

  navigateToDefault(params: { processId: NumberInput }): Promise<boolean> {
    const route = this.defaultRoute(params);
    return this._router.navigate(route.path, { queryParams: route.queryParams });
  }

  detailsRoute(params: {
    processId: NumberInput;
    customerId: NumberInput;
    customer?: CustomerDTO | CustomerInfoDTO;
  }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      { outlets: { primary: ['search', coerceNumberProperty(params.customerId)], side: 'results' } },
    ];

    const queryParams: Record<string, string> = {};

    if (params.customer) {
      queryParams.main_qs = params.customer?.customerNumber;
      queryParams.filter_customertype = '';
    }

    const urlTree = this._router.createUrlTree(path, { queryParams });

    return {
      path,
      urlTree,
      queryParams,
    };
  }

  navigateToDetails(params: {
    processId: NumberInput;
    customerId: NumberInput;
    customer?: CustomerDTO;
  }): Promise<boolean> {
    const route = this.detailsRoute(params);
    return this._router.navigate(route.path, { queryParams: route.queryParams });
  }

  addBillingAddressRoute(params: { processId: NumberInput; customerId: NumberInput }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: {
          primary: ['search', coerceNumberProperty(params.customerId), 'billingaddress', 'add'],
          side: 'results',
        },
      },
    ];

    const urlTree = this._router.createUrlTree(path, { queryParams: {} });

    return {
      path,
      urlTree,
      queryParams: {},
    };
  }

  navigateToAddBillingAddress(params: { processId: NumberInput; customerId: NumberInput }): Promise<boolean> {
    const route = this.addBillingAddressRoute(params);
    return this._router.navigate(route.path, { queryParams: route.queryParams });
  }

  editBillingAddressRoute(params: {
    processId: NumberInput;
    customerId: NumberInput;
    payerId: NumberInput;
  }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: {
          primary: [
            'search',
            coerceNumberProperty(params.customerId),
            'billingaddress',
            coerceNumberProperty(params.payerId),
            'edit',
          ],
          side: 'results',
        },
      },
    ];

    const urlTree = this._router.createUrlTree(path, { queryParams: {} });

    return {
      path,
      urlTree,
      queryParams: {},
    };
  }

  navigateToEditBillingAddress(params: {
    processId: NumberInput;
    customerId: NumberInput;
    payerId: NumberInput;
  }): Promise<boolean> {
    const route = this.editBillingAddressRoute(params);
    return this._router.navigate(route.path, { queryParams: route.queryParams });
  }

  addShippingAddressRoute(params: { processId: NumberInput; customerId: NumberInput }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: {
          primary: ['search', coerceNumberProperty(params.customerId), 'shippingaddress', 'add'],
          side: 'results',
        },
      },
    ];

    const urlTree = this._router.createUrlTree(path, { queryParams: {} });

    return {
      path,
      urlTree,
      queryParams: {},
    };
  }

  navigateToAddShippingAddress(params: { processId: NumberInput; customerId: NumberInput }): Promise<boolean> {
    const route = this.addShippingAddressRoute(params);
    return this._router.navigate(route.path, { queryParams: route.queryParams });
  }

  editShippingAddressRoute(params: {
    processId: NumberInput;
    customerId: NumberInput;
    shippingAddressId: NumberInput;
  }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: {
          primary: [
            'search',
            coerceNumberProperty(params.customerId),
            'shippingaddress',
            coerceNumberProperty(params.shippingAddressId),
            'edit',
          ],
          side: 'results',
        },
      },
    ];

    const urlTree = this._router.createUrlTree(path, { queryParams: {} });

    return {
      path,
      urlTree,
      queryParams: {},
    };
  }

  ordersRoute(params: {
    processId: NumberInput;
    customerId: NumberInput;
    customer?: CustomerDTO | CustomerInfoDTO;
  }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: {
          primary: ['search', coerceNumberProperty(params.customerId), 'orders'],
          side: 'results',
        },
      },
    ];

    const queryParams: Record<string, string> = {};

    if (params.customer) {
      queryParams.main_qs = params.customer?.customerNumber;
      queryParams.filter_customertype = '';
    }

    const urlTree = this._router.createUrlTree(path, { queryParams });

    return {
      path,
      urlTree,
      queryParams,
    };
  }

  navigateToOrders(params: { processId: NumberInput; customerId: NumberInput }): Promise<boolean> {
    const route = this.ordersRoute(params);
    return this._router.navigate(route.path, { queryParams: route.queryParams });
  }

  orderDetialsRoute(params: {
    processId: NumberInput;
    customerId: NumberInput;
    orderId: NumberInput;
    orderItemId?: NumberInput;
  }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: {
          primary: [
            'search',
            coerceNumberProperty(params.customerId),
            'orders',
            coerceNumberProperty(params.orderId),
            params.orderItemId ? coerceNumberProperty(params.orderItemId) : '',
          ]?.filter((v) => !!v),
          side: 'order-details',
        },
      },
    ];

    const urlTree = this._router.createUrlTree(path, { queryParams: {} });

    return {
      path,
      urlTree,
      queryParams: {},
    };
  }

  navigateToOrderDetails(params: {
    processId: NumberInput;
    customerId: NumberInput;
    orderId: NumberInput;
    orderItemId?: NumberInput;
  }): Promise<boolean> {
    const route = this.orderDetialsRoute(params);
    return this._router.navigate(route.path, { queryParams: route.queryParams, queryParamsHandling: 'merge' });
  }

  historyRoute(params: { processId: NumberInput; customerId: NumberInput }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: {
          primary: ['search', coerceNumberProperty(params.customerId), 'history'],
          side: 'results',
        },
      },
    ];

    const urlTree = this._router.createUrlTree(path, { queryParams: {} });

    return {
      path,
      urlTree,
      queryParams: {},
    };
  }

  editRoute(params: { processId: NumberInput; customerId: NumberInput; isB2b?: boolean }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: {
          primary: [
            'search',
            coerceNumberProperty(params.customerId),
            'edit',
            params.isB2b ? 'b2b' : undefined,
          ]?.filter((v) => !!v),
          side: 'results',
        },
      },
    ];

    const urlTree = this._router.createUrlTree(path, { queryParams: {} });

    return {
      path,
      queryParams: urlTree.queryParams,
      urlTree,
    };
  }

  navigateToHistory(params: { processId: NumberInput; customerId: NumberInput }): Promise<boolean> {
    const route = this.historyRoute(params);
    return this._router.navigate(route.path, { queryParams: route.queryParams });
  }

  filterRoute(params: { processId: NumberInput; comingFrom?: string }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: {
          primary: ['search', 'filter'],
          side: 'results',
        },
      },
    ];

    const urlTree = this._router.createUrlTree(path, { queryParams: { comingFrom: params.comingFrom } });

    return {
      path,
      queryParams: urlTree.queryParams,
      urlTree,
    };
  }

  navigateToFilter(params: { processId: NumberInput; comingFrom: string }): Promise<boolean> {
    const route = this.filterRoute(params);
    return this._router.navigate(route.path, { queryParams: route.queryParams });
  }

  listRoute(params: { processId: NumberInput; filter?: Filter }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: { primary: ['search', 'list'], side: null },
      },
    ];

    const queryParams = params.filter?.getQueryParams() ?? {};

    const urlTree = this._router.createUrlTree(path, { queryParams });

    return {
      path,
      queryParams,
      urlTree,
    };
  }

  kundenkarteRoute(params: { processId: NumberInput; customerId: NumberInput }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: {
          primary: ['search', coerceNumberProperty(params.customerId), 'kundenkarte'],
          side: 'results',
        },
      },
    ];

    const urlTree = this._router.createUrlTree(path, { queryParams: {} });

    return {
      path,
      urlTree,
      queryParams: {},
    };
  }

  orderDetailsHistoryRoute(params: {
    processId: NumberInput;
    customerId: NumberInput;
    orderId: NumberInput;
    orderItemId: number;
  }): NavigationRoute {
    const path = [
      '/kunde',
      coerceNumberProperty(params.processId),
      'customer',
      {
        outlets: {
          primary: [
            'search',
            coerceNumberProperty(params.customerId),
            'orders',
            coerceNumberProperty(params.orderId),
            coerceNumberProperty(params.orderItemId),
            'history',
          ],
          side: 'order-details',
        },
      },
    ];

    const urlTree = this._router.createUrlTree(path, { queryParams: {} });

    return {
      path,
      urlTree,
      queryParams: {},
    };
  }
}
