"""C-3 Problem Management / C-4 용량 관리 / C-5 서비스 카탈로그 통합 테스트"""
import sys, ast, os

os.environ.setdefault("GUARDIA_SECRET_KEY", "test-c345-secret-key-32bytes-padded!")
os.environ.setdefault("DATABASE_URL", "sqlite+aiosqlite:///./test_c345.db")

ok = True

print("=== 1. 구문 검사 ===")
files = [
    "routers/problem.py", "routers/capacity.py", "routers/catalog.py",
    "models.py", "main.py"
]
for f in files:
    try:
        with open(f, encoding="utf-8") as fh:
            src = fh.read()
        ast.parse(src)
        print(f"  OK  {f}")
    except SyntaxError as e:
        print(f"  ERR {f}: {e}")
        ok = False

print("\n=== 2. C-3 Problem Management 확인 ===")
with open("models.py", encoding="utf-8") as f:
    models_src = f.read()
with open("routers/problem.py", encoding="utf-8") as f:
    prob_src = f.read()

prob_checks = [
    (models_src, "class ProblemRecord(Base):", "ProblemRecord ORM"),
    (models_src, "class ProblemNote(Base):", "ProblemNote ORM"),
    (models_src, "class ProblemStatus(str, Enum):", "ProblemStatus Enum"),
    (models_src, "INVESTIGATING", "INVESTIGATING 상태"),
    (models_src, "RCA_DONE", "RCA_DONE 상태"),
    (models_src, "WORKAROUND", "WORKAROUND 상태"),
    (models_src, "known_error", "known_error 컬럼"),
    (models_src, "root_cause", "root_cause 컬럼"),
    (models_src, "tb_problem", "tb_problem 테이블"),
    (prob_src, '@router.post("/"', "POST 문제 생성"),
    (prob_src, '@router.get("/known-errors"', "Known Error DB"),
    (prob_src, '@router.post("/{prb_id}/rca"', "RCA 기록"),
    (prob_src, '@router.post("/{prb_id}/workaround"', "임시 해결"),
    (prob_src, '@router.post("/{prb_id}/resolve"', "해결 처리"),
    (prob_src, '@router.post("/{prb_id}/close"', "종결 처리"),
    (prob_src, '@router.post("/{prb_id}/notes"', "활동 노트"),
    (prob_src, "PRB-", "Problem ID 형식 (PRB-)"),
]
for src, sym, desc in prob_checks:
    status = "OK" if sym in src else "ERR"
    if status == "ERR":
        ok = False
    print(f"  {status}  {desc}")

print("\n=== 3. C-4 용량 관리 확인 ===")
with open("routers/capacity.py", encoding="utf-8") as f:
    cap_src = f.read()

cap_checks = [
    (models_src, "class CapacityPlan(Base):", "CapacityPlan ORM"),
    (models_src, "class CapacityStatus(str, Enum):", "CapacityStatus Enum"),
    (models_src, "forecast_3m", "3개월 예측 컬럼"),
    (models_src, "forecast_6m", "6개월 예측 컬럼"),
    (models_src, "forecast_12m", "12개월 예측 컬럼"),
    (models_src, "expansion_needed_at", "확장 필요 시점 컬럼"),
    (models_src, "growth_rate", "월 성장률 컬럼"),
    (models_src, "tb_capacity_plan", "tb_capacity_plan 테이블"),
    (cap_src, '@router.get("/dashboard"', "대시보드"),
    (cap_src, '@router.post("/plans"', "용량 계획 등록"),
    (cap_src, '@router.get("/plans"', "용량 계획 목록"),
    (cap_src, '@router.post("/plans/{plan_id}/recalculate"', "재계산"),
    (cap_src, '@router.get("/alerts"', "경보 목록"),
    (cap_src, '@router.get("/trends/{source}"', "트렌드"),
    (cap_src, "_calc_forecasts", "예측 계산 함수"),
    (cap_src, "_calc_status", "상태 계산 함수"),
    (cap_src, "OVERLOAD", "OVERLOAD 상태"),
]
for src, sym, desc in cap_checks:
    status = "OK" if sym in src else "ERR"
    if status == "ERR":
        ok = False
    print(f"  {status}  {desc}")

print("\n=== 4. C-5 서비스 카탈로그 확인 ===")
with open("routers/catalog.py", encoding="utf-8") as f:
    cat_src = f.read()

cat_checks = [
    (models_src, "class ServiceItem(Base):", "ServiceItem ORM"),
    (models_src, "class ServiceStatus(str, Enum):", "ServiceStatus Enum"),
    (models_src, "sla_response_h", "응답 SLA 컬럼"),
    (models_src, "sla_resolve_h", "해결 SLA 컬럼"),
    (models_src, "sla_availability", "가용성 SLA 컬럼"),
    (models_src, "approval_required", "승인 필요 컬럼"),
    (models_src, "request_count", "요청 카운트 컬럼"),
    (models_src, "tb_service_catalog", "tb_service_catalog 테이블"),
    (cat_src, '@router.get("/"', "카탈로그 목록"),
    (cat_src, '@router.post("/"', "카탈로그 등록"),
    (cat_src, '@router.get("/{service_id}"', "서비스 상세"),
    (cat_src, '@router.post("/{service_id}/request"', "서비스 요청 (SR 생성)"),
    (cat_src, '@router.get("/categories"', "카테고리 목록"),
    (cat_src, '@router.get("/stats"', "통계"),
    (cat_src, "SVC-", "서비스 ID 형식 (SVC-)"),
    (cat_src, "PENDING_APPROVAL", "승인 필요 SR 상태"),
]
for src, sym, desc in cat_checks:
    status = "OK" if sym in src else "ERR"
    if status == "ERR":
        ok = False
    print(f"  {status}  {desc}")

print("\n=== 5. main.py 등록 확인 ===")
with open("main.py", encoding="utf-8") as f:
    main_src = f.read()

for sym, desc in [
    ("problem", "C-3 problem 라우터"),
    ("problem.router", "problem 라우터 등록"),
    ("capacity", "C-4 capacity 라우터"),
    ("capacity.router", "capacity 라우터 등록"),
    ("catalog", "C-5 catalog 라우터"),
    ("catalog.router", "catalog 라우터 등록"),
]:
    status = "OK" if sym in main_src else "ERR"
    if status == "ERR":
        ok = False
    print(f"  {status}  {desc}")

print("\n=== 6. _calc_forecasts 수학 검증 ===")
try:
    import importlib.util, math
    spec = importlib.util.spec_from_file_location("cap_mod", "routers/capacity.py")
    cap_mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(cap_mod)

    # 월 10% 성장률로 현재값 100
    f3, f6, f12, _ = cap_mod._calc_forecasts(100.0, 10.0, 200.0)
    expected_f3  = round(100.0 * 1.1**3, 2)   # 133.1
    expected_f12 = round(100.0 * 1.1**12, 2)  # 313.84

    assert abs(f3 - expected_f3) < 0.1, f"3개월 예측 오류: {f3} != {expected_f3}"
    assert abs(f12 - expected_f12) < 0.5, f"12개월 예측 오류: {f12} != {expected_f12}"
    print(f"  OK  forecast(100, 10%, 3M) = {f3} (기대: {expected_f3})")
    print(f"  OK  forecast(100, 10%, 12M) = {f12} (기대: {expected_f12})")

    # 성장률 0이면 None 반환
    f3_0, _, _, _ = cap_mod._calc_forecasts(100.0, 0.0, 200.0)
    assert f3_0 is None, f"성장률 0에서 None 반환해야 함: {f3_0}"
    print(f"  OK  성장률 0 → None 반환")

except AssertionError as e:
    print(f"  ERR  {e}")
    ok = False
except Exception as e:
    print(f"  ERR  _calc_forecasts 오류: {type(e).__name__}: {e}")
    ok = False

print("\n=== 7. _calc_status 임계값 검증 ===")
try:
    # OVERLOAD: current >= crit * 1.1
    status = cap_mod._calc_status(100.0, 75.0, 90.0)
    assert status == "OVERLOAD", f"OVERLOAD 판정 실패: {status}"
    print(f"  OK  100% (crit=90%) → {status}")

    status = cap_mod._calc_status(92.0, 75.0, 90.0)
    assert status == "CRITICAL", f"CRITICAL 판정 실패: {status}"
    print(f"  OK  92% (crit=90%) → {status}")

    status = cap_mod._calc_status(80.0, 75.0, 90.0)
    assert status == "WARNING", f"WARNING 판정 실패: {status}"
    print(f"  OK  80% (warn=75%) → {status}")

    status = cap_mod._calc_status(50.0, 75.0, 90.0)
    assert status == "NORMAL", f"NORMAL 판정 실패: {status}"
    print(f"  OK  50% → {status}")

except AssertionError as e:
    print(f"  ERR  {e}")
    ok = False
except Exception as e:
    print(f"  ERR  _calc_status 오류: {type(e).__name__}: {e}")

print("\n=== 8. Problem / Capacity / Service ID 형식 검증 ===")
from datetime import datetime
today = datetime.utcnow().strftime("%Y%m%d")
ids = {
    f"PRB-{today}-0001": 17,   # PRB-YYYYMMDD-NNNN = 4+8+1+4 = 17
    f"SVC-0001": 8,             # SVC-NNNN = 4+4 = 8
}
for id_val, expected_len in ids.items():
    status = "OK" if len(id_val) == expected_len else "WARN"
    print(f"  {status}  {id_val} ({len(id_val)}자, 기대:{expected_len}자)")

print("\n=== C-3/C-4/C-5 통합 테스트 완료 ===")
if ok:
    print("모든 검사 통과")
else:
    sys.exit(1)
