import { callUnomi, callElasticsearch } from "../utils/connection";
import { validateSegmentObject, reformatSegment, validateSegmentCountObject } from "../utils/validation";
import { FilteredResponse } from "../../src/types/sdkResponse";
import { UsedProperties } from "../../src/types/segments";
import { SegmentProfileCountProperties } from "../../src/types/segments"

async function resolveReformatSegment(url: string, headers: Record<string, string>): FilteredResponse { // format segment to have correct form
    const callObjectPromise = await callUnomi("GET", url, null, headers, 200); // get segment

    if (callObjectPromise.statusCode === 200) { // if call success
        return new Promise((resolve, reject) => { // return formatted segment result object as a new promise
            resolve(reformatSegment(callObjectPromise, callObjectPromise.responseData)); // format segment and return object that needs to be resolved
        });
    }

    else { // call not success
        return new Promise((resolve, reject) => { // return result object as a new promise
            resolve(callObjectPromise); // object that needs to be resolved
        });
    }
}

/**
 * @function getAll
 * @param {string} baseUrl 
 * @param {Record<string, string>} headers 
 * @param {string} sortOrder 
 * @param {number} limit 
 * @param {number} offset 
 * @returns {FilteredResponse}
 */
export function getAll(baseUrl: string, headers: Record<string, string>, sortOrder: string, limit: number, offset: number): FilteredResponse { // get all segments
    const url = baseUrl + `/cxs/segments?size=${limit}&offset=${offset}&sort=${sortOrder}`; // segment endpoint

    return callUnomi("GET", url, null, headers, 200); // return result object
}

/**
 * @function get
 * @param {string} baseUrl 
 * @param {Record<string, string>} headers 
 * @param {string} segmentId 
 * @returns {FilteredResponse}
 */
export function get(baseUrl: string, headers: Record<string, string>, segmentId: string): FilteredResponse { // get specific segment
    const url = baseUrl + `/cxs/segments/${segmentId}`; // segment endpoint

    return resolveReformatSegment(url, headers); // return formatted segment
}

/**
 * @function create
 * @param {string} baseUrl 
 * @param {Record<string, string>} headers 
 * @param {object} properties 
 * @returns {FilteredResponse}
 */
export function create(baseUrl: string, headers: Record<string, string>, params: UsedProperties): FilteredResponse { // create segment
    const url = baseUrl + `/cxs/segments`; // segment endpoint

    const validatedSegmentObject = validateSegmentObject(params, false); // validate given segment

    if (validatedSegmentObject.areSubConditionsValid) { // check if subconditions are valid
        return callUnomi("POST", url, validatedSegmentObject.segmentObject, headers, 204); // return result object
    }

    else { // subconditions are not valid
        return callUnomi("POST", url, validatedSegmentObject.segmentObject, headers, 204, validatedSegmentObject.errors); // return result object
    }
}

/**
 * @function update
 * @param {string} baseUrl 
 * @param {Record<string, string>} headers 
 * @param {object} properties 
 * @returns {FilteredResponse}
 */
export function update(baseUrl: string, headers: Record<string, string>, params: UsedProperties): FilteredResponse { // update segment
    const url = baseUrl + `/cxs/segments`; // segment endpoint

    const validatedSegmentObject = validateSegmentObject(params, true); // validate given segment

    if (validatedSegmentObject.areSubConditionsValid) { // check if subconditions are valid
        return callUnomi("POST", url, validatedSegmentObject.segmentObject, headers, 204); // return result object
    }

    else { // subconditions are not valid
        return callUnomi("POST", url, validatedSegmentObject.segmentObject, headers, 204, validatedSegmentObject.errors); // return result object
    }
}

/**
 * @function delete
 * @param {string} baseUrl 
 * @param {Record<string, string>} headers 
 * @param {string} segmentId 
 * @returns {FilteredResponse}
 */
export function deleteSegment(baseUrl: string, headers: Record<string, string>, segmentId: string): FilteredResponse { // delete segment
    const url = baseUrl + `/cxs/segments/${segmentId}`; // segment endpoint

    return callUnomi("DELETE", url, null, headers, 200); // return result object
}

/**
 * @function count
 * @param {string} baseUrl 
 * @param {Record<string, string>} headers 
 * @param {SegmentProfileCountProperties} params 
 * @returns {FilteredResponse}
 */
export function profileCount(baseUrl: string, headers: Record<string, string>, params: SegmentProfileCountProperties): FilteredResponse { // get all used profile properties
    const url = baseUrl + `/context-profile/_count`; // profile endpoint

    const validatedParams = validateSegmentCountObject(params);

    if (validatedParams.isValid) { // check if segments and operator are valid
        
        var query = "";

        let segments = validatedParams.segments; // get the validated segments
        let operator = validatedParams.operator; // get the validated operator
        let queryOperator = " " + operator + " ";
    
        for (let index in segments) { // for every segment
            if (query != "") { // for every segment, except for the first one
                query += queryOperator // add the query operator (usually either " AND " or " OR ")
            }
            query += segments[index]; // add the segment uuid
        }
    
        // create the body for the api call
        let body = {
            query: {
                query_string: {
                    query: query,
                    default_field: "segments"
                }
            }
        }
    
        return callElasticsearch("POST", url, body, headers, 200); // return result object
    }

    else { // segments or operator are not valid
        return callElasticsearch("POST", url, null, headers, 200, validatedParams.errors); // return result object
    }

}
