
import { Resource, IResourceArgs } from "./Resource";
import { IFacetValue, IFilter, ISearchResponse, ISearchHit, API_SearchConfig, API_Config } from "../Types";
import { transformAndValidateSync } from "class-transformer-validator";
import { INavLink } from "src";
import { request } from "https";
import { ISearchPageProps } from "src/Core";

export interface ISearchArgs extends IResourceArgs {
    rootMapId: string;
}

export interface IFacet  {
    id: string;
    title: string;
    count: number;
    children: Array<IFacet>;
}

interface IRequestParams {
    startOffset: number;
    endOffset: number;
    queryString: string;
    refineToPaths?: string[];
    facetRequests?: Array<any>;
    drilldowns?: Array<any>;
    hierarchical_facets?: Boolean;
}

interface IInputSearchParams {
    queryString: string;
    page?: number;
    sectionPath?: string | string[];
    facetRequests?: Array<any>;
    drilldowns?: Array<any>
}

export class Search extends Resource {
    private searchFolders: {};
    // private search_filters: Array<{
    //     label: string;
    //     key: string;
    //     parent_taxon: string;
    // }>;
    private search_facets: Record<string, IFacetValue[]> = {};

    private rootMapId: string;
    private rows_per_page: any;

    constructor({ rootMapId, axios, config }: ISearchArgs) {
        super({ axios, config });
        this.rootMapId = rootMapId;
    }

    // public async get_filters(): Promise<IFilter[]> {
    //     await this.setup_search();
    //     return this.search_filters;
    // }

    public async get_search_facets(): Promise<Record<string, IFacetValue[]>> {
        await this.setup_search();
        return this.search_facets;
    }

    public async get_results_per_page(): Promise<any> {
        await this.setup_search();
        return this.rows_per_page;
    }

    public async get_facets(facetRequests: string[]): Promise<Array<IFacet>> {
        const request_params: IRequestParams = {
            queryString: "*", 
            facetRequests: facetRequests.map(facetRequest => ([facetRequest])), 
            startOffset: 0,
            endOffset: 1,
            hierarchical_facets: true
        };
        const response = await this.axios.post(
            "/search",
            JSON.stringify(request_params),
            {
                headers: {
                    "Content-Type": "text/plain",
                },
            },
        );
        const returnedFacets: Array<IFacet> = response.data.hierarchicalFacets;
      
        return returnedFacets;
    }

    public async executeSearch({queryString, page = 0, sectionPath, facetRequests, drilldowns}: IInputSearchParams): Promise<ISearchResponse> {
        await this.setup_search();

        let refineToPaths: string[];
        if (Array.isArray(sectionPath)){
            refineToPaths = sectionPath
        }else if(sectionPath){
            refineToPaths = [sectionPath]
        }; 

        const request_params: IRequestParams = {
            queryString,
            refineToPaths, 
            startOffset: page * this.rows_per_page,
            endOffset: (page + 1) * this.rows_per_page - 1,
            facetRequests: facetRequests,
            drilldowns: drilldowns
        };

        console.log(request_params);

        const response = await this.axios.post(
            "/search",
            JSON.stringify(request_params),
            {
                headers: {
                    "Content-Type": "text/plain",
                },
            },
        );
        if (response.data.totalResults == null) {
            throw "Search response missing total results";
        }
        let transformed = response.data.hits;

        transformed = transformed.map(obj => {
            obj.breadcrumbs = obj.breadcrumbs.filter(b => b.href !== "");
            transformAndValidateSync(ISearchHit, obj);
            return obj;
        });
        return { results: transformed, total_count: response.data.totalResults};
    }

    private async setup_search() {
        const config = await this.config.get();
        this.rows_per_page = config.search.results_per_page;
        // this.search_filters = config.search.filters;

        // Adhering to unintuitive search query protocol here
        // this.searchFolders = config.search.folders.reduce((acc, obj) => {
        //     acc[obj] = true;
        //     return acc;
        // }, {});

        // const transformer = el => ({
        //     facet_name: el.navtitle,
        //     id: el.value,
        //     children: el.children.length > 0 ? el.children.map(transformer) : [],
        // });
    }
}
