package com.erp.tenant;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 서브도메인 → (db_name, company_code) 매핑.
 * 메타 DB (COMPANY_MNG) 에서 조회, ConcurrentHashMap 으로 캐시.
 * null 결과(= 매핑 없음)는 캐시하지 않음 — 신규 회사 프로비저닝 직후 바로 반영되게.
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CompanyResolver {

    private final SqlSession sqlSession;

    /** subdomain → Resolved (db_name, company_code). 둘 다 묶어 한 번의 쿼리로 캐시. */
    public record Resolved(String dbName, String companyCode) {}

    private final Map<String, Resolved> cache = new ConcurrentHashMap<>();

    /**
     * @return 매핑 있으면 Resolved, 없으면 null.
     */
    public Resolved resolve(String subdomain) {
        if (subdomain == null || subdomain.isBlank()) return null;

        Resolved cached = cache.get(subdomain);
        if (cached != null) return cached;

        Map<String, Object> params = new HashMap<>();
        params.put("subdomain", subdomain);
        Map<String, Object> row = sqlSession.selectOne("tenant.resolveTenantBySubdomain", params);
        if (row == null) return null;

        String dbName = (String) row.get("db_name");
        String companyCode = (String) row.get("company_code");
        if (dbName == null) return null;

        Resolved r = new Resolved(dbName, companyCode);
        cache.put(subdomain, r);
        log.debug("[CompanyResolver] resolved: {} -> db={}, company={}", subdomain, dbName, companyCode);
        return r;
    }

    /** 하위 호환: db_name 만 필요할 때 */
    public String resolveDbName(String subdomain) {
        Resolved r = resolve(subdomain);
        return r == null ? null : r.dbName();
    }

    /** company_code 만 필요할 때 */
    public String resolveCompanyCode(String subdomain) {
        Resolved r = resolve(subdomain);
        return r == null ? null : r.companyCode();
    }

    /** 특정 서브도메인 캐시 무효화 (회사 수정/삭제 시) */
    public void invalidate(String subdomain) {
        if (subdomain != null) cache.remove(subdomain);
    }

    /** 전체 캐시 무효화 (운영 도구/디버그용) */
    public void invalidateAll() {
        cache.clear();
    }
}
