#!/usr/bin/env python3
"""
GUARDiA ITSM — DB 초기화 헬퍼 (설치 스크립트용)

스키마 불일치 감지 시 자동 백업 후 재초기화.
설치·업그레이드 시 setup 스크립트에서 호출한다.

사용법:
  python tools/db_init.py [--force]
  --force: 기존 DB 강제 삭제 후 재초기화 (신규 설치)
"""
import asyncio
import os
import shutil
import sys
from datetime import datetime
from pathlib import Path

# itsm/ 디렉토리를 Python 경로에 추가
ITSM_DIR = Path(__file__).parent.parent
sys.path.insert(0, str(ITSM_DIR))
os.chdir(str(ITSM_DIR))

# .env 로드 (있으면)
try:
    from dotenv import load_dotenv
    load_dotenv(".env")
except ImportError:
    pass


FORCE = "--force" in sys.argv
DB_PATH = Path(os.getenv("DATABASE_URL", "sqlite+aiosqlite:///./guardia_itsm.db")
               .replace("sqlite+aiosqlite:///", "").replace("./", ""))


def _backup_db():
    if DB_PATH.exists():
        backup = DB_PATH.with_suffix(
            f".backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}.db"
        )
        shutil.copy2(DB_PATH, backup)
        print(f"[BACKUP] {DB_PATH} → {backup}")
        return backup
    return None


async def _verify_schema(max_retries: int = 1) -> bool:
    """
    현재 DB 스키마가 모델과 일치하는지 확인.
    주요 테이블의 컬럼 존재 여부를 점검한다.
    """
    from database import SessionLocal
    from models import User
    from sqlalchemy import select, text

    for attempt in range(max_retries + 1):
        try:
            async with SessionLocal() as db:
                # User 테이블 전체 컬럼 조회 (가장 자주 변경되는 테이블)
                await db.execute(select(User).limit(1))
            return True
        except Exception as e:
            if attempt == 0:
                print(f"[SCHEMA] 스키마 불일치 감지: {e}")
            return False
    return False


async def main():
    from database import init_db, engine
    from core.seed import seed_all
    from database import SessionLocal

    db_is_sqlite = not os.getenv("DATABASE_URL", "").startswith("postgresql")

    # ── 신규 설치 모드 --force ──────────────────────────────────────────────
    if FORCE and db_is_sqlite and DB_PATH.exists():
        print("[FORCE] 기존 DB 삭제 후 재초기화...")
        _backup_db()
        DB_PATH.unlink()

    # ── DB 존재 시 스키마 검증 ──────────────────────────────────────────────
    if db_is_sqlite and DB_PATH.exists():
        print(f"[CHECK] 기존 DB 스키마 검증: {DB_PATH}")
        schema_ok = await _verify_schema()
        if not schema_ok:
            print("[MIGRATE] 스키마 불일치 — 백업 후 재초기화합니다.")
            _backup_db()
            DB_PATH.unlink()
            print("[INFO] 새 스키마로 DB를 생성합니다.")
        else:
            print("[OK] 스키마 정상")

    # ── 테이블 생성 ────────────────────────────────────────────────────────
    try:
        await init_db()
        print("[OK] DB 테이블 초기화 완료")
    except Exception as e:
        print(f"[ERROR] DB 초기화 실패: {e}")
        sys.exit(1)

    # ── 시드 데이터 삽입 ──────────────────────────────────────────────────
    try:
        async with SessionLocal() as db:
            await seed_all(db)
        print("[OK] 시드 데이터 삽입 완료")
    except Exception as e:
        print(f"[WARN] 시드 데이터 삽입 오류 (무시): {e}")

    await engine.dispose()
    print("[OK] DB 초기화 완료")


def _copy_offline_assets():
    """폐쇄망 정적 파일 복사 (있는 경우)."""
    import shutil
    offline_chart = ITSM_DIR.parent / "setup" / "offline" / "common" / "chart.umd.min.js"
    target_chart  = ITSM_DIR / "static" / "chart.umd.min.js"
    if offline_chart.exists() and not target_chart.exists():
        shutil.copy2(offline_chart, target_chart)
        print(f"[OK] Chart.js 오프라인 파일 복사: {target_chart}")


if __name__ == "__main__":
    _copy_offline_assets()
    asyncio.run(main())
