package com.zioinfo.kintex.auth;

import java.util.Map;

/**
 * 인증 주체 — JWT에서 복원되는 사용자 신원 + 행사별 역할 맵.
 *
 * @param userId       사용자 식별자
 * @param displayName  표시 이름
 * @param eventRoles   행사ID → 역할 (행사 단위 RBAC). 홀매니저는 전체 열람이므로 별도 플래그.
 * @param hallManager  킨텍스 내부 홀매니저 여부(전체 행사 열람+승인)
 * @param roleCode     전역 역할(app_user.role_code — ADMIN/MANAGER/…, 없으면 null). 순증 필드(하위호환).
 * @param tenantId     소속 테넌트(전시관) — JWT {@code tid} 클레임(멀티테넌시 2단계, §1A-3-2).
 *                     기존(tid 부재) 토큰·비인증 경로는 기준 테넌트 {@code 'kintex'}로 복원(회귀 0).
 */
public record KintexPrincipal(
        String userId,
        String displayName,
        Map<String, EventRole> eventRoles,
        boolean hallManager,
        String roleCode,
        String tenantId
) {

    /** 기준 테넌트(#1 KINTEX) — {@code com.zioinfo.kintex.tenant.TenantContext.DEFAULT_TENANT}와 일치. */
    private static final String DEFAULT_TENANT = "KINTEX";

    /** 하위호환 보조 생성자 — 테넌트 미상(tid 없는 기존 토큰) 경로용. 기존 5-인자 호출 유지·테넌트는 기준값. */
    public KintexPrincipal(String userId, String displayName,
                           Map<String, EventRole> eventRoles, boolean hallManager, String roleCode) {
        this(userId, displayName, eventRoles, hallManager, roleCode, DEFAULT_TENANT);
    }

    /** 하위호환 보조 생성자 — roleCode·테넌트 미상 경로용. 기존 4-인자 호출 유지(테스트 회귀 방지). */
    public KintexPrincipal(String userId, String displayName,
                           Map<String, EventRole> eventRoles, boolean hallManager) {
        this(userId, displayName, eventRoles, hallManager, null, DEFAULT_TENANT);
    }

    /** 전역 시스템관리자(app_user.role_code='ADMIN') 여부 — 전 행사 열람+승인(홀매니저 상위). */
    public boolean isAdmin() {
        return "ADMIN".equalsIgnoreCase(roleCode);
    }

    /** 해당 행사에서 사용자의 역할(없으면 null). 홀매니저·ADMIN은 항상 HALL_MANAGER로 간주. */
    public EventRole roleFor(String eventId) {
        if (hallManager || isAdmin()) {
            return EventRole.HALL_MANAGER;
        }
        return eventRoles == null ? null : eventRoles.get(eventId);
    }

    public boolean hasAccess(String eventId) {
        return hallManager || isAdmin() || (eventRoles != null && eventRoles.containsKey(eventId));
    }
}
