import { PostType } from '../enums/post-type.enum';
import { buildWaveformPeakSet } from './waveform.util';

type VariantSet = {
  originalUrl?: string;
  lowUrl?: string;
  mediumUrl?: string;
  highUrl?: string;
} | null;

type PostMediaInput = {
  postType?: PostType | string;
  imageUrls?: string[];
  imageItems?: Array<{ url?: string; caption?: string; altText?: string; order?: number }>;
  imageVariants?: VariantSet[];
  videoUrl?: string;
  hlsUrl?: string;
  audioUrl?: string;
  thumbnailUrl?: string;
  thumbnailVariants?: VariantSet;
  waveformPeaks?: number[];
  waveformPeaksPreview?: number[];
  waveformPeaksDetailed?: number[];
  durationSeconds?: number | null;
};

const firstNonEmpty = (...values: Array<string | undefined | null>): string =>
  values.find((value): value is string => typeof value === 'string' && value.trim().length > 0) ?? '';

const normalizeVariantSet = (variants: VariantSet) => {
  if (!variants) {
    return null;
  }

  return {
    originalUrl: variants.originalUrl ?? '',
    lowUrl: variants.lowUrl ?? variants.mediumUrl ?? variants.highUrl ?? variants.originalUrl ?? '',
    mediumUrl: variants.mediumUrl ?? variants.highUrl ?? variants.lowUrl ?? variants.originalUrl ?? '',
    highUrl: variants.highUrl ?? variants.mediumUrl ?? variants.originalUrl ?? variants.lowUrl ?? '',
  };
};

const preferredImageUrl = (variants: ReturnType<typeof normalizeVariantSet>, fallback = ''): string =>
  firstNonEmpty(variants?.mediumUrl, variants?.highUrl, variants?.lowUrl, variants?.originalUrl, fallback);

export const buildPostMediaResponse = (post: PostMediaInput) => {
  const imageUrls = Array.isArray(post.imageUrls) ? post.imageUrls : [];
  const imageItems = Array.isArray(post.imageItems) ? post.imageItems : [];
  const imageVariants = Array.isArray(post.imageVariants) ? post.imageVariants : [];
  const thumbnailVariants = normalizeVariantSet(post.thumbnailVariants ?? null);
  const fallbackImageItems: NonNullable<PostMediaInput['imageItems']> = imageUrls.map((url, index) => ({
    url,
    caption: '',
    altText: '',
    order: index,
  }));
  const images = (imageItems.length ? imageItems : fallbackImageItems).map(
    (item, index) => {
      const variants = normalizeVariantSet(imageVariants[index] ?? null);
      const url = item.url || imageUrls[index] || '';
      return {
        url: preferredImageUrl(variants, url),
        originalUrl: firstNonEmpty(variants?.originalUrl, url),
        variants,
        caption: item.caption ?? '',
        altText: item.altText ?? '',
        order: typeof item.order === 'number' ? item.order : index,
      };
    },
  );

  const mediaType =
    post.postType === PostType.IMAGE && images.length
      ? PostType.IMAGE
      : post.postType === PostType.VIDEO || post.videoUrl || post.hlsUrl
        ? PostType.VIDEO
        : post.postType === PostType.AUDIO || post.audioUrl
          ? PostType.AUDIO
          : PostType.TEXT;
  const thumbnailUrl = preferredImageUrl(thumbnailVariants, post.thumbnailUrl ?? '');
  const preferredPlaybackUrl =
    mediaType === PostType.VIDEO
      ? firstNonEmpty(post.hlsUrl, post.videoUrl)
      : mediaType === PostType.AUDIO
        ? post.audioUrl ?? ''
        : '';
  const displayUrl =
    mediaType === PostType.IMAGE
      ? images[0]?.url ?? ''
      : mediaType === PostType.VIDEO || mediaType === PostType.AUDIO
        ? thumbnailUrl
        : '';
  const waveformSet =
    mediaType === PostType.AUDIO
      ? buildWaveformPeakSet(
          post.waveformPeaksDetailed?.length
            ? post.waveformPeaksDetailed
            : post.waveformPeaksPreview?.length
              ? post.waveformPeaksPreview
              : post.waveformPeaks,
          post.durationSeconds,
        )
      : { waveformPeaks: [], waveformPeaksPreview: [], waveformPeaksDetailed: [] };

  return {
    mediaType,
    displayUrl,
    thumbnailUrl,
    thumbnailVariants,
    preferredPlaybackUrl,
    hlsUrl: post.hlsUrl ?? '',
    videoUrl: post.videoUrl ?? '',
    audioUrl: post.audioUrl ?? '',
    images,
    durationSeconds: post.durationSeconds ?? null,
    waveformPeaks: waveformSet.waveformPeaks,
    waveformPeaksPreview: waveformSet.waveformPeaksPreview,
    waveformPeaksDetailed: waveformSet.waveformPeaksDetailed,
    isPlayable: mediaType === PostType.VIDEO ? !!preferredPlaybackUrl : mediaType === PostType.AUDIO ? !!post.audioUrl : false,
  };
};
