package incheon.product.common.geo3d;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.within;

/**
 * GeoView3DProperties 기본값 보호(회귀) 테스트.
 * 3D 뷰어 설정의 기본값이 실수로 변경되는 것을 방어한다.
 */
class GeoView3DPropertiesTest {

    private final GeoView3DProperties props = new GeoView3DProperties();

    @Test
    @DisplayName("Viewer 기본값 — 인천 초기 좌표/줌 설정이 유지된다")
    void viewerDefaults() {
        GeoView3DProperties.Viewer v = props.getViewer();
        assertThat(v.getInitialLongitude()).isCloseTo(126.70486, within(0.001));
        assertThat(v.getInitialLatitude()).isCloseTo(37.45247, within(0.001));
        assertThat(v.getInitialHeight()).isCloseTo(400.0, within(0.1));
        assertThat(v.getInitialHeading()).isCloseTo(0.0, within(0.1));
        assertThat(v.getInitialPitch()).isCloseTo(-44.0, within(0.1));
        assertThat(v.getMinZoomDistance()).isCloseTo(150.0, within(0.1));
        assertThat(v.getMaxZoomDistance()).isCloseTo(500000.0, within(0.1));
    }

    @Test
    @DisplayName("TrafficApi 기본값이 유지된다")
    void trafficApiDefaults() {
        GeoView3DProperties.TrafficApi api = props.getTrafficApi();
        assertThat(api.getBaseUrl()).isEqualTo("https://openapi.its.go.kr:9443");
        assertThat(api.getApiKey()).isNull();
        assertThat(api.getConnectTimeoutMs()).isEqualTo(5000);
        assertThat(api.getReadTimeoutMs()).isEqualTo(7000);
        assertThat(api.getTrafficPath()).isEqualTo("/trafficInfo");
        assertThat(api.getCctvPath()).isEqualTo("/cctvInfo");
    }

    @Test
    @DisplayName("GisManager 기본값 — 모든 필드가 null이다")
    void gisManagerDefaults() {
        GeoView3DProperties.GisManager gm = props.getGisManager();
        assertThat(gm.getBuildUrl()).isNull();
        assertThat(gm.getManagerUrl()).isNull();
        assertThat(gm.getPrefix()).isNull();
    }

    @Test
    @DisplayName("ExternalApi 기본값 — apiKey가 null이다")
    void externalApiDefaults() {
        assertThat(props.getExternalApi().getApiKey()).isNull();
    }

    @Test
    @DisplayName("Schema 기본값이 유지된다")
    void schemaDefaults() {
        GeoView3DProperties.Schema schema = props.getSchema();
        assertThat(schema.getExternal()).isEqualTo("icsgp");
        assertThat(schema.getMain()).isEqualTo("iccom");
        assertThat(schema.getExt()).isEqualTo("icext");
    }

    @Test
    @DisplayName("Data3d 기본값 — 3D 모델 테이블명이 유지된다")
    void data3dDefaults() {
        GeoView3DProperties.Data3d d = props.getData3d();
        assertThat(d.getModelTable()).isEqualTo("iccom.dgtltw_mdl_mng");
    }

    @Test
    @DisplayName("중첩 객체가 null이 아니다")
    void nestedObjectsNotNull() {
        assertThat(props.getViewer()).isNotNull();
        assertThat(props.getTrafficApi()).isNotNull();
        assertThat(props.getGisManager()).isNotNull();
        assertThat(props.getExternalApi()).isNotNull();
        assertThat(props.getSchema()).isNotNull();
        assertThat(props.getData3d()).isNotNull();
    }

    @Test
    @DisplayName("Setter로 값을 변경할 수 있다")
    void setterWorks() {
        GeoView3DProperties.Viewer v = props.getViewer();
        v.setInitialLongitude(127.0);
        assertThat(v.getInitialLongitude()).isCloseTo(127.0, within(0.001));

        GeoView3DProperties.Schema schema = props.getSchema();
        schema.setMain("newSchema");
        assertThat(schema.getMain()).isEqualTo("newSchema");

        GeoView3DProperties.Data3d d = props.getData3d();
        d.setModelTable("custom.table_name");
        assertThat(d.getModelTable()).isEqualTo("custom.table_name");
    }
}
