import {
  ApiSchemas,
  Cart,
  CartItem,
  CategoryListingResultSW,
  Collection,
  Menu,
  Page,
  Product,
  ProductOption,
  ProductVariant
} from './types';
import {
  ExtendedCart,
  ExtendedCategory,
  ExtendedCmsPage,
  ExtendedLineItem,
  ExtendedProduct,
  ExtendedProductListingResult
} from './api-extended';
import { ListItem } from 'components/layout/search/filter';
import { isSeoUrls } from 'lib/shopware/helpers';

export function transformMenu(res: ExtendedCategory[], type: string) {
  const menu: Menu[] = [];

  res.map((item) => menu.push(transformMenuItem(item, type)));

  return menu;
}

function transformMenuItem(item: ExtendedCategory, type: string): Menu {
  const path = isSeoUrls()
    ? item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo
      ? type === 'footer-navigation'
        ? '/cms/' + item.seoUrls[0].seoPathInfo
        : '/search/' + item.seoUrls[0].seoPathInfo
      : ''
    : type === 'footer-navigation'
    ? '/cms/' + item.id ?? ''
    : '/search/' + item.id ?? '';

  // @ToDo: currently only footer-navigation is used for cms pages, this need to be more dynamic (shoud depending on the item)
  return {
    id: item.id ?? '',
    title: item.name,
    children: item.children?.map((item) => transformMenuItem(item, type)) ?? [],
    path: path,
    type: item.children && item.children.length > 0 ? 'headline' : 'link'
  };
}

export function transformPage(
  category: ExtendedCategory,
  seoUrlElement?: ApiSchemas['SeoUrl']
): Page {
  let plainHtmlContent;
  if (category.cmsPage) {
    const cmsPage: ExtendedCmsPage = category.cmsPage;
    plainHtmlContent = transformToPlainHtmlContent(cmsPage);
  }

  return {
    id: seoUrlElement?.id ?? category.id ?? '',
    title: category.translated?.metaTitle ?? category.name ?? '',
    handle: seoUrlElement?.seoPathInfo ?? category.id ?? '',
    body: plainHtmlContent ?? category.description ?? '',
    bodySummary: category.translated?.metaDescription ?? category.description ?? '',
    seo: {
      title: category.translated?.metaTitle ?? category.name ?? '',
      description: category.translated?.metaDescription ?? category.description ?? ''
    },
    createdAt: seoUrlElement?.createdAt ?? category.createdAt ?? '',
    updatedAt: seoUrlElement?.updatedAt ?? category.updatedAt ?? '',
    routeName: seoUrlElement?.routeName,
    originalCmsPage: category.cmsPage,
    foreignKey: seoUrlElement?.foreignKey ?? category.id
  };
}

export function transformToPlainHtmlContent(cmsPage: ExtendedCmsPage): string {
  let plainHtmlContent = '';

  cmsPage.sections?.map((section) => {
    section.blocks?.map((block) => {
      block.slots?.map((slot) => {
        if (slot.slot === 'content' && slot.config?.content) {
          const currentContent: string = slot.config.content.value + '';
          // we do not add content with h1, because will be added via template already
          if (!currentContent.match(/(<\/?h)([1])/)) {
            plainHtmlContent += currentContent;
          }
        }
      });
    });
  });

  return plainHtmlContent;
}

export function transformCollection(
  resCategory: ExtendedCategory,
  seoUrlElement?: ApiSchemas['SeoUrl']
) {
  return {
    handle: seoUrlElement?.seoPathInfo ?? resCategory.id ?? '',
    title: resCategory.translated?.metaTitle ?? resCategory.name ?? '',
    description: resCategory.description ?? '',
    seo: {
      title: resCategory.translated?.metaTitle ?? resCategory.name ?? '',
      description: resCategory.translated?.metaDescription ?? resCategory.description ?? ''
    },
    updatedAt:
      seoUrlElement?.updatedAt ??
      seoUrlElement?.createdAt ??
      resCategory.updatedAt ??
      resCategory.createdAt
  };
}

export function transformSubCollection(
  category: CategoryListingResultSW,
  parentCollectionName?: string
): Collection[] {
  const collection: Collection[] = [];

  if (category.elements && category.elements[0] && category.elements[0].children) {
    // we do not support type links at the moment and show only visible categories
    category.elements[0].children
      .filter((item) => item.visible)
      .filter((item) => item.type !== 'link')
      .map((item) => {
        const handle =
          isSeoUrls() && item.seoUrls ? findHandle(item.seoUrls, parentCollectionName) : item.id;
        if (handle) {
          collection.push({
            handle: handle,
            title: item.translated?.metaTitle ?? item.name ?? '',
            description: item.description ?? '',
            seo: {
              title: item.translated?.metaTitle ?? item.name ?? '',
              description: item.translated?.metaDescription ?? item.description ?? ''
            },
            childCount: item.childCount ?? 0,
            updatedAt: item.updatedAt ?? item.createdAt ?? ''
          });
        }
      });
  }

  return collection;
}

// small function to find longest handle and to make sure parent collection name is in the path
function findHandle(seoUrls: ApiSchemas['SeoUrl'][], parentCollectionName?: string): string {
  let handle: string = '';
  seoUrls.map((item) => {
    if (
      !item.isDeleted &&
      item.isCanonical &&
      item.seoPathInfo &&
      item.seoPathInfo.length > handle.length &&
      item.seoPathInfo.includes(parentCollectionName ?? '')
    ) {
      handle = item.seoPathInfo;
    }
  });

  return handle;
}

export function transformCollectionToList(collection: Collection[]): ListItem[] {
  const listItem: ListItem[] = [];

  if (collection && collection.length > 0) {
    collection.map((item) => {
      // we asume that when there is not product child count it must be a cms page
      const pagePrefix = item.childCount === 0 ? '/cms' : '/search';
      const newHandle = item.handle.replace('Main-navigation/', '');
      listItem.push({
        title: item.title,
        path: `${pagePrefix}/${newHandle}`
      });
    });
  }

  return listItem;
}

export function transformProducts(res: ExtendedProductListingResult): Product[] {
  const products: Product[] = [];

  if (res.elements && res.elements.length > 0) {
    res.elements.map((item) => products.push(transformProduct(item)));
  }

  return products;
}

export function transformProduct(item: ExtendedProduct): Product {
  const productOptions = transformOptions(item);
  const productVariants = transformVariants(item);

  let path = item.parentId ?? item.id ?? '';
  if (isSeoUrls()) {
    path =
      item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo
        ? item.seoUrls[0].seoPathInfo
        : '';
  }

  return {
    id: item.id ?? '',
    path: path,
    availableForSale: item.available ?? false,
    title: item.translated ? item.translated.name ?? '' : item.name,
    description: item.translated?.metaDescription
      ? item.translated.metaDescription ?? ''
      : item.metaDescription ?? '',
    descriptionHtml: item.translated?.description
      ? item.translated.description ?? ''
      : item.description ?? '',
    options: productOptions,
    priceRange: {
      maxVariantPrice: {
        amount: item.calculatedPrice?.totalPrice ? String(item.calculatedPrice?.totalPrice) : '0',
        currencyCode: 'EUR'
      },
      minVariantPrice: {
        amount: item.calculatedCheapestPrice?.totalPrice
          ? String(item.calculatedPrice?.totalPrice)
          : '0',
        currencyCode: 'EUR'
      }
    },
    variants: productVariants,
    featuredImage: {
      url: item.cover?.media?.url ?? '',
      altText: item.cover?.media?.translated?.alt ?? '',
      width: item.cover?.media?.metaData?.width ? Number(item.cover?.media?.metaData?.width) : 0,
      height: item.cover?.media?.metaData?.width ? Number(item.cover?.media?.metaData?.height) : 0
    },
    images: item.media
      ? item.media.map((img) => ({
          url: img.media?.url ?? '',
          altText: img.media?.translated?.alt ?? '',
          width: img.media?.metaData?.width ? Number(img.media?.metaData?.width) : 0,
          height: img.media?.metaData?.width ? Number(img.media?.metaData?.height) : 0
        }))
      : [],
    seo: {
      title: item.translated?.metaTitle ?? item.translated?.name ?? item.name ?? '',
      description: item.translated?.metaDescription ?? ''
    },
    tags: [''], // @ToDo: Add keywords or do we have tags?
    updatedAt: item.updatedAt ?? ''
  };
}

function transformOptions(parent: ExtendedProduct): ProductOption[] {
  // we only transform options for parents with children, ignore child products with options
  const productOptions: ProductOption[] = [];
  if (parent.children && parent.parentId === null && parent.children.length > 0) {
    const group: { [key: string]: string[] } = {};
    const groupId: { [key: string]: string } = {};
    parent.children.map((child) => {
      child.options?.map((option) => {
        if (option && option.group) {
          groupId[option.group.name] = option.groupId;
          group[option.group.name] = group[option.group.name]
            ? [...new Set([...(group[option.group.name] as []), ...[option.name]])]
            : [option.name];
        }
      });
    });

    for (const [key, value] of Object.entries(group)) {
      for (const [currentGroupName, currentGroupId] of Object.entries(groupId)) {
        if (key === currentGroupName) {
          productOptions.push({
            id: currentGroupId,
            name: key,
            values: value
          });
        }
      }
    }
  }

  return productOptions;
}

function transformVariants(parent: ExtendedProduct): ProductVariant[] {
  const productVariants: ProductVariant[] = [];
  if (parent.children && parent.parentId === null && parent.children.length > 0) {
    parent.children.map((child) => {
      if (child.id) {
        const selectedOptions: { name: string; value: string }[] = [];
        child.options?.map((option) => {
          if (option.group) {
            selectedOptions.push({
              name: option.group.name,
              value: option.name
            });
          }
        });
        const currentVariant: ProductVariant = {
          id: child.id,
          title: child.name,
          availableForSale: child.available ?? false,
          selectedOptions: selectedOptions,
          price: {
            amount: child.calculatedPrice?.totalPrice
              ? String(child.calculatedPrice?.totalPrice)
              : '0',
            currencyCode: 'EUR'
          }
        };

        productVariants.push(currentVariant);
      }
    });
  }

  return productVariants;
}

export function transformHandle(handle: string | []): string {
  let collectionName: string | [] | undefined = handle;
  if (Array.isArray(collectionName)) {
    collectionName = collectionName.join('/');
  }

  return collectionName ?? '';
}

export function transformCart(resCart: ExtendedCart): Cart {
  return {
    checkoutUrl: 'https://frontends-demo.vercel.app',
    cost: {
      subtotalAmount: {
        amount: resCart.price?.positionPrice?.toString() || '0',
        currencyCode: 'EUR'
      },
      totalAmount: {
        amount: resCart.price?.totalPrice?.toString() || '0',
        currencyCode: 'EUR'
      },
      totalTaxAmount: {
        amount: '0',
        currencyCode: 'EUR'
      }
    },
    id: resCart.token ?? '',
    lines:
      resCart.lineItems?.map((lineItem: ExtendedLineItem) => transformLineItem(lineItem)) || [],
    totalQuantity: resCart.lineItems ? calculateTotalCartQuantity(resCart.lineItems) : 0
  };
}

function calculateTotalCartQuantity(lineItems: ExtendedLineItem[]) {
  let totalQuantity = 0;
  lineItems.forEach((lineItem) => {
    totalQuantity += lineItem.quantity ?? 0;
  });

  return totalQuantity;
}

function transformLineItem(resLineItem: ExtendedLineItem): CartItem {
  return {
    id: resLineItem.id || '',
    quantity: resLineItem.quantity ?? 0,
    cost: {
      totalAmount: {
        amount: resLineItem.price?.totalPrice.toString() || '',
        currencyCode: 'EUR'
      }
    },
    merchandise: {
      id: resLineItem.referencedId ?? '',
      title: resLineItem.label ?? '',
      selectedOptions: [],
      product: {
        description: resLineItem.description ?? '',
        descriptionHtml: resLineItem.description ?? '',
        id: resLineItem.referencedId ?? '',
        images: [],
        path: resLineItem.referencedId ?? '',
        seo: {
          description: resLineItem.description ?? '',
          title: resLineItem.label ?? ''
        },
        availableForSale: true,
        featuredImage: {
          url: resLineItem.cover?.url ?? '',
          altText: resLineItem.cover?.translated?.alt ?? resLineItem.cover?.alt ?? '',
          width: Number(resLineItem.cover?.metaData?.width) ?? 0,
          height: Number(resLineItem.cover?.metaData?.height) ?? 0
        },
        options: [],
        variants: [],
        priceRange: {
          minVariantPrice: {
            amount: '', // @ToDo: should be correct value
            currencyCode: 'EUR'
          },
          maxVariantPrice: {
            amount: '', // @ToDo: should be correct value
            currencyCode: 'EUR'
          }
        },
        tags: [],
        title: resLineItem.label ?? '',
        updatedAt: resLineItem.payload?.updatedAt ?? resLineItem.payload?.createdAt ?? ''
      }
    }
  };
}