import { Axios } from './index';

/**
 * 공통 API 호출 서비스
 * @param {string} token - 인증 토큰
 * @param {string} endpointName - API 엔드포인트 이름
 * @param {Object} params - API 호출에 필요한 파라미터
 * @returns {Promise} API 호출 결과
 */
export const callAPI = async (apiConfig, endpointConfig, params = {}, options = {}) => {
	const token = sessionStorage.getItem('token');
	try {
		const { method, url, dataPath } = endpointConfig;
		const baseUrl = apiConfig.baseUrl || '';
		let fullUrl = `${baseUrl}${url}`;
		let requestParams = { ...params };

		if (options.pageField && options.pageField !== 'currentPage' && params.currentPage) {
			requestParams[options.pageField] = params.currentPage;
			delete requestParams.currentPage;
		}

		if (options.pageSizeField && options.pageSizeField !== 'pageSize' && params.pageSize) {
			requestParams[options.pageSizeField] = params.pageSize;
			delete requestParams.pageSize;
		}

		if (options.orderField && options.orderField !== 'orderBy' && params.orderBy) {
			requestParams[options.orderField] = params.orderBy;
			delete requestParams.orderBy;
		}

		if (options.paginationType === 'dynamodb' && options.lastPageKeyField && 'lastEvaluatedKey' in requestParams) {
			requestParams[options.lastPageKeyField] = requestParams.lastEvaluatedKey;
			delete requestParams.lastEvaluatedKey;
		}

		// URL 경로 파라미터 처리 (예: /users/:id)
		const pathParams = url.match(/:[a-zA-Z]+/g) || [];
		pathParams.forEach(param => {
			const paramName = param.substring(1); // ':id' -> 'id'
			if (params[paramName]) {
				fullUrl = fullUrl.replace(param, encodeURIComponent(params[paramName]));
				delete requestParams[paramName]; // URL에 사용된 파라미터는 제거
			}
		});

		// 기본 요청 설정
		const config = {
			headers: { Authorization: `Bearer ${token}` }
		};

		let response;

		switch (method.toLowerCase()) {
			case 'get':
				// GET 요청은 URL 쿼리 파라미터로 전달
				const queryParams = new URLSearchParams();
				Object.entries(requestParams).forEach(([key, value]) => {
						queryParams.append(key, value);
				});
				const queryString = queryParams.toString();
				response = await Axios.get(
					`${fullUrl}${queryString ? '?' + queryString : ''}`,
					config
				);
				break;

			case 'post':
				response = await Axios.post(fullUrl, requestParams, config);
				break;

			case 'put':
				response = await Axios.put(fullUrl, requestParams, config);
				break;

			case 'delete':
				response = await Axios.delete(fullUrl, {
					...config,
					data: requestParams
				});
				break;

			default:
				throw new Error(`Unsupported method: ${method}`);
		}

		// 데이터 경로에 따라 결과 반환
		if (dataPath) {
			return dataPath.split('.').reduce((obj, path) => obj && obj[path], response);
		}
		return response.data;
	} catch (error) {
		console.error(`API Call Error for ${apiConfig.baseUrl}${endpointConfig.url}:`, error);
		if (error instanceof Error) {
			throw new Error(`${endpointConfig.name || 'API'} Error: ${error.message}`);
		}
		throw error;
	}
};

/**
 * API 설정에서 엔드포인트 가져오기
 * @param {Object} apiConfig - API 설정 객체
 * @param {string} endpointName - 엔드포인트 이름
 * @returns {Object} 엔드포인트 설정
 */
export const getEndpoint = (apiConfig, endpointName) => {
	const endpoint = apiConfig.endpoints[endpointName];
	if (!endpoint) {
		throw new Error(`Endpoint not found: ${endpointName}`);
	}
	return endpoint;
};

/**
 * API 모듈 생성
 * @param {Object} apiConfig - API 설정 객체
 * @returns {Object} API 함수들을 포함한 객체
 */
export const createAPIModule = (apiConfig) => {
	const apiModule = {};

	Object.keys(apiConfig.endpoints).forEach(endpointName => {
		const endpoint = apiConfig.endpoints[endpointName];

		apiModule[endpointName] = async (token, params = {}, options = {}) => {
			// 단일 파라미터인 경우 처리
			const processedParams = typeof params !== 'object' ? { id: params } : params;
			return callAPI(token, apiConfig, endpoint, processedParams, options);
		};
	});

	return apiModule;
};