import { cache } from 'react';

import { getAnalysisElementMedusaProductIds } from '@/utils/medusa-product';
import { listProductTypes, listProducts } from '@lib/data/products';
import { listRegions } from '@lib/data/regions';
import type { StoreProduct, StoreProductType } from '@medusajs/types';

import type { AccountWithParams } from '@kit/accounts/types/accounts';
import type { AnalysisPackageWithVariant } from '@kit/shared/components/select-analysis-package';

import PersonalCode from '~/lib/utils';

import { loadCurrentUserAccount } from './load-user-account';

async function countryCodesLoader() {
  const countryCodes = await listRegions().then((regions) =>
    regions?.map((r) => r.countries?.map((c) => c.iso_2)).flat(),
  );
  return countryCodes ?? [];
}
export const loadCountryCodes = cache(countryCodesLoader);

async function productTypesLoader() {
  const { productTypes } = await listProductTypes();
  return productTypes ?? [];
}
export const loadProductTypes = cache(productTypesLoader);

function userSpecificVariantLoader({
  account,
}: {
  account: AccountWithParams;
}) {
  const { personal_code: personalCode } = account;
  if (!personalCode) {
    throw new Error('Personal code not found');
  }

  const {
    ageRange,
    gender: { value: gender },
  } = PersonalCode.parsePersonalCode(personalCode);

  return ({ product }: { product: StoreProduct }) => {
    const variants = product.variants;
    if (!variants) {
      return null;
    }

    const variant = variants.find((v) =>
      v.options?.every((o) => [ageRange, gender].includes(o.value)),
    );
    if (!variant) {
      return null;
    }
    return variant;
  };
}

async function analysisPackageElementsLoader({
  analysisPackagesWithVariant,
  countryCode,
}: {
  analysisPackagesWithVariant: AnalysisPackageWithVariant[];
  countryCode: string;
}) {
  const analysisElementMedusaProductIds = getAnalysisElementMedusaProductIds(
    analysisPackagesWithVariant,
  );
  if (analysisElementMedusaProductIds.length === 0) {
    return [];
  }

  const {
    response: { products },
  } = await listProducts({
    countryCode,
    queryParams: {
      id: analysisElementMedusaProductIds,
      limit: 100,
      order: 'title',
    },
  });

  const standardPackage = analysisPackagesWithVariant.find(
    ({ isStandard }) => isStandard,
  );
  const standardPlusPackage = analysisPackagesWithVariant.find(
    ({ isStandardPlus }) => isStandardPlus,
  );
  const premiumPackage = analysisPackagesWithVariant.find(
    ({ isPremium }) => isPremium,
  );
  if (!standardPackage || !standardPlusPackage || !premiumPackage) {
    return [];
  }

  const standardPackageAnalyses = getAnalysisElementMedusaProductIds([
    standardPackage,
  ]);
  const standardPlusPackageAnalyses = getAnalysisElementMedusaProductIds([
    standardPlusPackage,
  ]);
  const premiumPackageAnalyses = getAnalysisElementMedusaProductIds([
    premiumPackage,
  ]);

  return products.map(({ id, title, description }) => ({
    id,
    title,
    description,
    isIncludedInStandard: standardPackageAnalyses.includes(id),
    isIncludedInStandardPlus: standardPlusPackageAnalyses.includes(id),
    isIncludedInPremium: premiumPackageAnalyses.includes(id),
  }));
}

async function analysisPackagesWithVariantLoader({
  account,
  countryCode,
  productType,
}: {
  account: AccountWithParams;
  countryCode: string;
  productType: StoreProductType;
}) {
  const analysisPackagesResponse = await listProducts({
    countryCode,
    queryParams: { limit: 100, 'type_id[0]': productType.id },
  });

  const getVariant = userSpecificVariantLoader({ account });
  const analysisPackagesWithVariant =
    analysisPackagesResponse.response.products.reduce((acc, product) => {
      const variant = getVariant({ product });
      if (!variant) {
        return acc;
      }
      return [
        ...acc,
        {
          variant,
          variantId: variant.id,
          nrOfAnalyses: getAnalysisElementMedusaProductIds([
            { ...product, variant },
          ]).length,
          price: variant.calculated_price?.calculated_amount ?? 0,
          title: product.title,
          subtitle: product.subtitle,
          description: product.description,
          metadata: product.metadata,
          isStandard: product.metadata?.analysisPackageTier === 'standard',
          isStandardPlus:
            product.metadata?.analysisPackageTier === 'standard-plus',
          isPremium: product.metadata?.analysisPackageTier === 'premium',
        },
      ];
    }, [] as AnalysisPackageWithVariant[]);

  return analysisPackagesWithVariant;
}

async function analysisPackagesLoader() {
  const { account } = await loadCurrentUserAccount();
  if (!account) {
    throw new Error('Account not found');
  }

  const [countryCodes, productTypes] = await Promise.all([
    loadCountryCodes(),
    loadProductTypes(),
  ]);
  const countryCode = countryCodes[0]!;
  const productType = productTypes.find(
    ({ metadata }) => metadata?.handle === 'analysis-packages',
  );

  if (!productType) {
    return { analysisPackageElements: [], analysisPackages: [], countryCode };
  }

  const analysisPackagesWithVariant = await analysisPackagesWithVariantLoader({
    account,
    countryCode,
    productType,
  });
  if (!analysisPackagesWithVariant) {
    return { analysisPackageElements: [], analysisPackages: [], countryCode };
  }

  const analysisPackageElements = await analysisPackageElementsLoader({
    analysisPackagesWithVariant,
    countryCode,
  });

  return {
    analysisPackageElements,
    analysisPackages: analysisPackagesWithVariant,
    countryCode,
  };
}
export const loadAnalysisPackages = cache(analysisPackagesLoader);
