• Advanced search for manga with additional filters.

    Parameters

    • search: string

      Search query.

    • filters: { genres?: string[]; tags?: string[]; formats?: string[] } = {}

      Filter options.

    • page: number = 1

      Page number.

    • perPage: number = 50

      Results per page.

    • Optionaltoken: string

      Optional access token.

    • OptionalbypassCache: boolean

      Optional parameter to bypass cache.

    Returns Promise<SearchResult<AniListManga>>

    Promise resolving to search results.

    export async function advancedSearchManga(
    search: string,
    filters: {
    genres?: string[];
    tags?: string[];
    formats?: string[];
    } = {},
    page: number = 1,
    perPage: number = 50,
    token?: string,
    bypassCache?: boolean,
    ): Promise<SearchResult<AniListManga>> {
    // Generate cache key with additional filters
    const cacheKey = generateCacheKey(search, page, perPage, filters);

    // Check if we should bypass the cache
    if (!bypassCache && isCacheValid(searchCache, cacheKey)) {
    console.log(`📋 Using cached advanced search results for: "${search}"`);
    return searchCache[cacheKey].data;
    }

    if (bypassCache) {
    console.log(
    `🚨 FORCE SEARCH: Bypassing cache for "${search}" in client.advancedSearchManga - will make API request`,
    );
    }

    console.log(
    `🔍 Advanced search for manga: "${search}" with filters:`,
    filters,
    );

    try {
    // Map filters to variables
    const variables = {
    search,
    page,
    perPage,
    genre_in: filters.genres,
    tag_in: filters.tags,
    format_in: filters.formats,
    };

    console.log("Query:", ADVANCED_SEARCH_MANGA);
    console.log("Variables:", variables, { bypassCache });

    // Updated type parameter to correctly handle potential nested data structure
    const response = await request<{
    data?: { Page: SearchResult<AniListManga>["Page"] };
    Page?: SearchResult<AniListManga>["Page"];
    }>(ADVANCED_SEARCH_MANGA, variables, token, undefined, bypassCache);

    console.log("🔍 advancedSearchManga response:", response);

    // Validate the response structure before using it
    if (!response || !response.data) {
    console.error(
    `Invalid API response for advanced search "${search}":`,
    response,
    );
    throw new Error(`Invalid API response: missing data property`);
    }

    // Check if the API response has a nested data object (response.data.data structure)
    const responseData = response.data.data
    ? response.data.data
    : response.data;

    if (!responseData.Page) {
    console.error(
    `Invalid API response for advanced search "${search}": missing Page property`,
    responseData,
    );
    throw new Error(`Invalid API response: missing Page property`);
    }

    const result = { Page: responseData.Page };

    // Ensure media array exists (even if empty)
    if (!result.Page.media) {
    result.Page.media = [];
    }

    // Log the number of results found
    console.log(
    `🔍 Found ${result.Page.media.length} manga for advanced search "${search}" (page ${page}/${result.Page.pageInfo?.lastPage || 1})`,
    );

    // Cache the results if not bypassing cache
    if (!bypassCache) {
    searchCache[cacheKey] = {
    data: result,
    timestamp: Date.now(),
    };

    // Persist the updated cache
    persistSearchCache();
    console.log(
    `💾 Cached ${result.Page.media.length} advanced search results for "${search}"`,
    );
    } else {
    console.log(
    `🚨 FORCE SEARCH: Not caching advanced search results for "${search}" as bypassCache=true`,
    );
    }

    return result;
    } catch (error) {
    console.error(`Error in advanced search for: ${search}`, error);

    // Return a valid but empty result to prevent crashing
    const emptyResult: SearchResult<AniListManga> = {
    Page: {
    pageInfo: {
    total: 0,
    currentPage: page,
    lastPage: 1,
    hasNextPage: false,
    perPage,
    },
    media: [],
    },
    };

    return emptyResult;
    }
    }