'use client';

import { useQuery } from '@tanstack/react-query';
import { useMemo } from 'react';
import { deepCamelKeys } from 'string-ts';

import { useApiClient } from '@/lib/apiClient';
import { components } from '@/lib/gen';
import { ClientEntity } from '@/lib/typeUtils';

export type AlignedLyrics = NonNullable<
  ClientEntity<components['schemas']['AlignedLyricsV2Schema']>['alignedLyrics']
>;

export const alignedLyricsKeys = {
  all: [{ scope: 'alignedLyrics' }] as const,
  v2: ({ clipId }: { clipId: string }) =>
    [{ ...alignedLyricsKeys.all[0], entity: 'v2', clipId }] as const,
  hooks: ({ hookIds }: { hookIds: string[] }) =>
    [{ ...alignedLyricsKeys.all[0], entity: 'hooks', hookIds }] as const,
};

export function useAlignedLyricsV2(
  clipId: string,
  options?: {
    enabled?: boolean;
  }
) {
  const { enabled = true } = options || {};

  const apiClient = useApiClient();

  const alignedLyricsQuery = useQuery({
    enabled,
    queryKey: alignedLyricsKeys.v2({ clipId }),
    queryFn: async () => {
      const response = await apiClient.GET(
        '/api/gen/{clip_id}/aligned_lyrics/v2/',
        {
          params: { path: { clip_id: clipId } },
        }
      );
      if (response.error) {
        throw new Error((response as any).error);
      }
      return deepCamelKeys(response.data);
    },
    staleTime: 10 * 60 * 1000,
  });

  return useMemo(
    () => ({
      alignedLyrics: alignedLyricsQuery.data?.alignedLyrics || [],
      updatedTime: new Date(alignedLyricsQuery.dataUpdatedAt).toUTCString(),
      query: alignedLyricsQuery,
    }),
    [alignedLyricsQuery]
  );
}

/**
 * Use aligned lyrics given a list of hook IDs
 */
export function useHooksLyrics(
  hookIds: string | string[],
  options?: {
    enabled?: boolean;
  }
) {
  const ids = Array.isArray(hookIds) ? hookIds : [hookIds];
  const { enabled = true } = options || {};

  const apiClient = useApiClient();

  const hooksLyricsQuery = useQuery({
    enabled,
    queryKey: alignedLyricsKeys.hooks({ hookIds: ids }),
    queryFn: async () => {
      const response = await apiClient.POST(
        '/api/video/hooks/fetch_hook_lyrics',
        {
          body: {
            hook_ids: ids,
          },
        }
      );
      if (response.error) {
        throw new Error((response as any).error);
      }
      // Preserve the original keys of `hook_lyrics` because they are the hook IDs
      const { hook_lyrics: srcHookLyrics, ...restResponse } = response.data;
      return {
        ...deepCamelKeys(restResponse),
        hookLyrics: Object.fromEntries(
          Object.entries(srcHookLyrics).map(([key, value]) => [
            key,
            deepCamelKeys(value),
          ])
        ),
      };
    },
    staleTime: 10 * 60 * 1000,
  });

  const singleHookId = typeof hookIds === 'string' ? hookIds : undefined;

  return useMemo(
    () => ({
      alignedLyrics: singleHookId
        ? hooksLyricsQuery.data?.hookLyrics?.[singleHookId]
        : undefined,
      alignedLyricsById: hooksLyricsQuery.data?.hookLyrics || {},
      updatedTime: new Date(hooksLyricsQuery.dataUpdatedAt).toUTCString(),
      query: hooksLyricsQuery,
    }),
    [hooksLyricsQuery, singleHookId]
  );
}
