package com.eactive.eai.kjb.errors;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;

class BearerTokenErrorTest {

	@Test
	void testCase001_잘못된GrantType() throws Exception {
		// given
		String url = TestConfig.getBaseUrl("/auth/oauth/v2/token");

		List<NameValuePair> params = new ArrayList<>();
		params.add(new BasicNameValuePair("grant_type", "password"));
		params.add(new BasicNameValuePair("client_id", "AyeWx0OpYLJbHpZ21DDSxYfQPmD5Ckn8"));
		params.add(new BasicNameValuePair("client_secret", "KwBYJT1m1v3SUvzN2HPHhy2Ad9Q2GADbgWkYZZg9Ybbc8R1uEuBJNQ9oVl13b1qiXwYvDWTaX0EanxY4SMjNfnBBsZzfNoMwwDPTb3IjQy5k3CRxTAYzcSnmzlC4FSsG"));
		params.add(new BasicNameValuePair("scope", "api"));

		// when
		try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new UrlEncodedFormEntity(params));

			String responseBody = httpClient.execute(httpPost, response -> {
				String body = EntityUtils.toString(response.getEntity());
				System.out.println("Response Body: " + body);

				// then
				assertEquals(401, response.getCode());
				return body;
			});

			// MessageUtil.makeJsonErrorMessage 기본 포맷 검증
			ErrorResponseValidator.validateErrorFormat(responseBody);
		}
	}

	@Test
	void testCase002_존재하지않는ClientId() throws Exception {
		// given
		String url = TestConfig.getBaseUrl("/auth/oauth/v2/token");

		List<NameValuePair> params = new ArrayList<>();
		params.add(new BasicNameValuePair("grant_type", "client_credentials"));
		params.add(new BasicNameValuePair("client_id", "INVALID_CLIENT_ID"));
		params.add(new BasicNameValuePair("client_secret", "invalid_secret"));
		params.add(new BasicNameValuePair("scope", "api"));

		// when
		try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new UrlEncodedFormEntity(params));

			String responseBody = httpClient.execute(httpPost, response -> {
				String body = EntityUtils.toString(response.getEntity());
				System.out.println("Response Body: " + body);

				// then
				assertEquals(401, response.getCode());
				return body;
			});

			// MessageUtil.makeJsonErrorMessage 기본 포맷 검증
			ErrorResponseValidator.validateErrorFormat(responseBody);
		}
	}

	@Test
	void testCase003_잘못된ClientSecret() throws Exception {
		// given
		String url = TestConfig.getBaseUrl("/auth/oauth/v2/token");

		List<NameValuePair> params = new ArrayList<>();
		params.add(new BasicNameValuePair("grant_type", "client_credentials"));
		params.add(new BasicNameValuePair("client_id", "AyeWx0OpYLJbHpZ21DDSxYfQPmD5Ckn8"));
		params.add(new BasicNameValuePair("client_secret", "WRONG_SECRET"));
		params.add(new BasicNameValuePair("scope", "api"));

		// when
		try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new UrlEncodedFormEntity(params));

			String responseBody = httpClient.execute(httpPost, response -> {
				String body = EntityUtils.toString(response.getEntity());
				System.out.println("Response Body: " + body);

				// then
				assertEquals(401, response.getCode());
				return body;
			});

			// MessageUtil.makeJsonErrorMessage 기본 포맷 검증
			ErrorResponseValidator.validateErrorFormat(responseBody);
		}
	}

	@Test
	void testCase004_Scope없음() throws Exception {
		// given
		String url = TestConfig.getBaseUrl("/auth/oauth/v2/token");

		List<NameValuePair> params = new ArrayList<>();
		params.add(new BasicNameValuePair("grant_type", "client_credentials"));
		params.add(new BasicNameValuePair("client_id", "AyeWx0OpYLJbHpZ21DDSxYfQPmD5Ckn8"));
		params.add(new BasicNameValuePair("client_secret", "KwBYJT1m1v3SUvzN2HPHhy2Ad9Q2GADbgWkYZZg9Ybbc8R1uEuBJNQ9oVl13b1qiXwYvDWTaX0EanxY4SMjNfnBBsZzfNoMwwDPTb3IjQy5k3CRxTAYzcSnmzlC4FSsG"));
		params.add(new BasicNameValuePair("scope", ""));

		// when
		try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new UrlEncodedFormEntity(params));

			String responseBody = httpClient.execute(httpPost, response -> {
				String body = EntityUtils.toString(response.getEntity());
				System.out.println("Response Body: " + body);

				// then
				assertEquals(401, response.getCode());
				return body;
			});

			// MessageUtil.makeJsonErrorMessage 기본 포맷 검증
			ErrorResponseValidator.validateErrorFormat(responseBody);
		}
	}

	@Test
	void testCase005_허용되지않은Scope() throws Exception {
		// given
		String url = TestConfig.getBaseUrl("/auth/oauth/v2/token");

		List<NameValuePair> params = new ArrayList<>();
		params.add(new BasicNameValuePair("grant_type", "client_credentials"));
		params.add(new BasicNameValuePair("client_id", "AyeWx0OpYLJbHpZ21DDSxYfQPmD5Ckn8"));
		params.add(new BasicNameValuePair("client_secret", "KwBYJT1m1v3SUvzN2HPHhy2Ad9Q2GADbgWkYZZg9Ybbc8R1uEuBJNQ9oVl13b1qiXwYvDWTaX0EanxY4SMjNfnBBsZzfNoMwwDPTb3IjQy5k3CRxTAYzcSnmzlC4FSsG"));
		params.add(new BasicNameValuePair("scope", "invalid_scope"));

		// when
		try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new UrlEncodedFormEntity(params));

			String responseBody = httpClient.execute(httpPost, response -> {
				String body = EntityUtils.toString(response.getEntity());
				System.out.println("Response Body: " + body);

				// then
				assertEquals(401, response.getCode());
				return body;
			});

			// MessageUtil.makeJsonErrorMessage 기본 포맷 검증
			ErrorResponseValidator.validateErrorFormat(responseBody);
		}
	}
}
