'use server';

import { getAnalysisElementMedusaProductIds } from '@/utils/medusa-product';
import { listProducts } from '@lib/data/products';
import { listRegions } from '@lib/data/regions';
import { StoreOrder } from '@medusajs/types';

import { getAnalyses } from './analyses.service';
import { getAnalysisElements } from './analysis-element.service';

const ANALYSIS_PACKAGE_HANDLE_PREFIX = 'analysis-package-';

export async function getOrderedAnalysisIds({
  medusaOrder,
}: {
  medusaOrder: StoreOrder;
}): Promise<
  {
    analysisElementId?: number;
    analysisId?: number;
  }[]
> {
  const countryCodes = await listRegions();
  const countryCode = countryCodes[0]!.countries![0]!.iso_2!;

  async function getOrderedAnalysisElements(medusaOrder: StoreOrder) {
    const originalIds = (medusaOrder?.items ?? [])
      .map((a) => a.product?.metadata?.analysisIdOriginal)
      .filter((a) => typeof a === 'string') as string[];
    const analysisElements = await getAnalysisElements({ originalIds });
    return analysisElements.map(({ id }) => ({ analysisElementId: id }));
  }

  async function getOrderedAnalyses(medusaOrder: StoreOrder) {
    const originalIds = (medusaOrder?.items ?? [])
      .map((a) => a.product?.metadata?.analysisIdOriginal)
      .filter((a) => typeof a === 'string') as string[];
    const analyses = await getAnalyses({ originalIds });
    return analyses.map(({ id }) => ({ analysisId: id }));
  }

  async function getOrderedAnalysisPackages(medusaOrder: StoreOrder) {
    const orderedPackages = (medusaOrder?.items ?? []).filter(({ product }) =>
      product?.handle.startsWith(ANALYSIS_PACKAGE_HANDLE_PREFIX),
    );
    const orderedPackageIds = orderedPackages
      .map(({ product }) => product?.id)
      .filter(Boolean) as string[];
    if (orderedPackageIds.length === 0) {
      return [];
    }
    console.info(`Order has ${orderedPackageIds.length} packages`);
    const {
      response: { products: orderedPackagesProducts },
    } = await listProducts({
      countryCode,
      queryParams: { limit: 100, id: orderedPackageIds },
    });
    console.info(
      `Order has ${orderedPackagesProducts.length} packages = ${JSON.stringify(orderedPackageIds, null, 2)}`,
    );
    if (orderedPackagesProducts.length !== orderedPackageIds.length) {
      throw new Error(
        `Got ${orderedPackagesProducts.length} ordered packages products, expected ${orderedPackageIds.length}`,
      );
    }

    const ids = getAnalysisElementMedusaProductIds(
      orderedPackagesProducts.map(({ id, metadata }) => ({
        metadata,
        variant: orderedPackages.find(({ product }) => product?.id === id)
          ?.variant,
      })),
    );
    if (ids.length === 0) {
      return [];
    }
    const {
      response: { products: analysisPackagesProducts },
    } = await listProducts({
      countryCode,
      queryParams: { limit: 100, id: ids },
    });
    if (analysisPackagesProducts.length !== ids.length) {
      throw new Error(
        `Got ${analysisPackagesProducts.length} analysis packages products, expected ${ids.length}`,
      );
    }

    const originalIds = analysisPackagesProducts
      .map(({ metadata }) => metadata?.analysisIdOriginal)
      .filter((id) => typeof id === 'string');
    if (originalIds.length !== ids.length) {
      throw new Error(
        `Got ${originalIds.length} analysis packages products with analysisIdOriginal, expected ${ids.length}`,
      );
    }
    const analysisElements = await getAnalysisElements({ originalIds });

    return analysisElements.map(({ id }) => ({ analysisElementId: id }));
  }

  const [analysisPackageElements, orderedAnalysisElements, orderedAnalyses] =
    await Promise.all([
      getOrderedAnalysisPackages(medusaOrder),
      getOrderedAnalysisElements(medusaOrder),
      getOrderedAnalyses(medusaOrder),
    ]);

  return [
    ...analysisPackageElements,
    ...orderedAnalysisElements,
    ...orderedAnalyses,
  ];
}
