import { Page } from '@playwright/test';
import { type AxiosInstance, type AxiosResponse } from 'axios';
import * as fs from 'fs';
import * as path from 'path';

export async function httpGet<T>(client: AxiosInstance, url: string): Promise<T> {
    const [isSuccess, response] = await handleHttp(client.get<T>(url));
    if(isSuccess) {
        return response;
    }

    console.error(`An error occurred calling GET ${url}\nError:${response}`);
    throw response;
}

export async function httpPost<T, D>(client: AxiosInstance, url: string, data: D): Promise<T> {
    const [isSuccess, response] = await handleHttp(client.post<T>(url, data));
    if(isSuccess) {
        return response;
    }

    console.error(`An error occurred calling POST ${url}\nError:${response}`);
    throw response;
}

export function handleHttp<T>(request: Promise<AxiosResponse<T>>): Promise<[isSuccess: true, data: T] | [isSuccess: false, error: Error]> {
    return request.then(data => {
        return [true, data.data] as [true, T]
    }).catch((error: Error) => {
        return [false, error] as [false, Error]
    })
}

export function buildQueryString<T>(data: T): URLSearchParams {
    const params: Record<string, string> = {};
    for (const key in data) {
        const value = data[key];
        params[key] = `${value}`;
    }
    return new URLSearchParams(params);
}

export function forceAPIError(page: Page, endpoint: string) {
    page.route('**/*', (route) => {
        return route.request().url().includes(endpoint)
            ? route.abort()
            : route.continue()
    });
}

// Utility method to return mock response based on endpoint and scenario
export function getMockedApiResponse(endpoint: string, scenario: string): object | null {
    const mockResponsesDir = path.resolve(__dirname, '../../tests/mockResponses');
    const configFilePath = path.join(mockResponsesDir, 'mockResponsesConfig.json');

    if (fs.existsSync(configFilePath)) {
        const config = JSON.parse(fs.readFileSync(configFilePath, 'utf-8'));
        const scenarioConfig = config[scenario];
        const commonConfig = config['common'];

        let mockFilePath = scenarioConfig ? scenarioConfig[endpoint] : null;
        if (!mockFilePath && commonConfig) {
            mockFilePath = commonConfig[endpoint];
        }

        if (mockFilePath) {
            const filePath = path.join(mockResponsesDir, mockFilePath);
            if (fs.existsSync(filePath)) {
                const mockResponse = fs.readFileSync(filePath, 'utf-8');
                return JSON.parse(mockResponse);
            }
        }
    }

    return null;
}

// Utility method for mocking API responses
export function mockApiResponse(page: Page, endpoint: string, scenario: string, mockTestingFlag: boolean) {
    const mockResponse = getMockedApiResponse(endpoint, scenario);
    page.route(`**/${endpoint}`, route => {
        if (mockResponse && mockTestingFlag) {
            route.fulfill({
                status: 200,
                contentType: 'application/json',
                body: JSON.stringify(mockResponse)
            });
        } else {
            route.continue();
        }
    });
}