package com.zioinfo.kintex.auth;

import com.zioinfo.kintex.common.error.ApiException;
import com.zioinfo.kintex.common.error.ErrorCode;
import com.zioinfo.kintex.tenant.EventTenantMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
 * 멀티테넌시 2단계 격리 단위테스트 — {@link EventAccessGuard}가 교차-테넌트 행사 접근을 fail-closed로 차단한다(§1A-3-2).
 * 홀매니저처럼 전 행사 접근권(hasAccess=true)이 넓은 주체도 다른 테넌트 행사는 열람 불가여야 한다.
 */
class EventAccessGuardTenantTest {

    private EventTenantMapper eventTenantMapper;
    private EventAccessGuard guard;

    @BeforeEach
    void setUp() {
        eventTenantMapper = mock(EventTenantMapper.class);
        guard = new EventAccessGuard(eventTenantMapper);
    }

    /** 홀매니저(전 행사 접근권)라도 타 테넌트 행사면 403 — 교차-테넌트 격리. */
    @Test
    void blocksCrossTenantEventAccessEvenForHallManager() {
        KintexPrincipal kintexHallManager = new KintexPrincipal(
                "u-kintex", "홀매니저", Map.of(), true, "MANAGER", "kintex");
        when(eventTenantMapper.findEventTenant("ev-coex")).thenReturn("coex");

        ApiException ex = assertThrows(ApiException.class,
                () -> guard.requireEventAccess(kintexHallManager, "ev-coex"));
        assertEquals(ErrorCode.FORBIDDEN, ex.getCode());
    }

    /** 동일 테넌트 행사는 정상 통과. */
    @Test
    void allowsSameTenantEventAccess() {
        KintexPrincipal kintexHallManager = new KintexPrincipal(
                "u-kintex", "홀매니저", Map.of(), true, "MANAGER", "kintex");
        when(eventTenantMapper.findEventTenant("ev-kintex")).thenReturn("kintex");

        assertDoesNotThrow(() -> guard.requireEventAccess(kintexHallManager, "ev-kintex"));
    }

    /** 행사 미존재(테넌트 미확인)는 기존 접근권 판정을 그대로 유지(회귀 0) — 여기선 통과. */
    @Test
    void passesWhenEventTenantUnknown() {
        KintexPrincipal principal = new KintexPrincipal(
                "u-kintex", "홀매니저", Map.of(), true, "MANAGER", "kintex");
        when(eventTenantMapper.findEventTenant("ev-missing")).thenReturn(null);

        assertDoesNotThrow(() -> guard.requireEventAccess(principal, "ev-missing"));
    }
}
