"""
GUI smoke 테스트 — QApplication을 띄우지 않고 UI 다이얼로그 instantiation만 확인.
실제 .show()는 헤드리스 환경에서 위험하므로 생성 단계까지만 검증.
"""
import os
import sys
import tempfile

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

# Qt platform plugin: offscreen으로 실제 창 안 뜨게
os.environ['QT_QPA_PLATFORM'] = 'offscreen'

# 백그라운드 휴일 동기화 스레드 비활성화 (DB lock / segfault 방지)
os.environ['CLOCKOUT_DISABLE_HOLIDAY_SYNC'] = '1'

from PyQt5.QtWidgets import QApplication
app = QApplication.instance() or QApplication(sys.argv)

PASS, FAIL = [], []


def case(label, fn):
    try:
        fn()
        PASS.append(label)
        print(f"[PASS] {label}")
    except Exception as e:
        FAIL.append((label, f"{type(e).__name__}: {e}"))
        print(f"[FAIL] {label}: {type(e).__name__}: {e}")


# Fresh DB
from core.database import Database
db_path = os.path.join(tempfile.gettempdir(), 'clockout_gui_test.db')
if os.path.exists(db_path):
    os.remove(db_path)
db = Database(db_path)


def test_settings_view():
    from ui.settings_view import SettingsView
    dlg = SettingsView(db=db)
    # 단축근무 7h30m 프리셋 적용
    dlg.work_preset_combo.setCurrentIndex(1)  # "단축근무 7시간 30분"
    assert dlg.work_hours_spin.value() == 7
    assert dlg.work_minutes_spin.value() == 30
    assert dlg.lunch_spin.value() == 30
    dlg.deleteLater()


def test_help_view():
    from ui.help_view import HelpView
    dlg = HelpView()
    # 6개 탭 존재
    tabs = dlg.findChild(type(dlg).__mro__[0])
    from PyQt5.QtWidgets import QTabWidget
    tab_widget = dlg.findChild(QTabWidget)
    assert tab_widget is not None
    assert tab_widget.count() == 6
    dlg.deleteLater()


def test_mini_widget():
    from ui.mini_widget import MiniWidget
    w = MiniWidget()
    w.update_remaining("01:30:00")
    assert w.time_label.text() == "01:30:00"
    w.update_remaining("+00:30:00")
    assert "추가" in w.title_label.text()
    w.deleteLater()


def test_chart_widget():
    from ui.chart_widget import make_chart_widget, draw_daily_hours, draw_weekday_avg
    w = make_chart_widget()
    # 빈 records로도 안전하게 그려져야
    draw_daily_hours(w, [])
    # 데이터가 있을 때
    records = [
        {'date': '2026-04-25', 'total_hours': 8.5, 'overtime_minutes': 30},
        {'date': '2026-04-26', 'total_hours': 9.0, 'overtime_minutes': 60},
    ]
    draw_daily_hours(w, records)
    draw_weekday_avg(w, records)
    w.deleteLater()


def test_stats_view():
    from ui.stats_view import StatsView
    dlg = StatsView(db=db)
    # 데이터 없어도 정상 로드
    assert dlg.weekly_total_card is not None
    dlg.deleteLater()


def test_calendar_view():
    from ui.calendar_view import CalendarView
    dlg = CalendarView(db=db)
    dlg.deleteLater()


def test_main_window_init():
    """MainWindow 초기화 — 가장 무거운 케이스"""
    # QLocalServer 충돌 방지: 프로세스 ID 기반 이름 변경 어려움 → init만 확인
    from ui.main_window import MainWindow
    from datetime import date as _date
    # MainWindow load_today_data에서 QMessageBox를 띄우지 않도록 오늘 출근 기록을 미리 삽입
    today = _date.today().isoformat()
    conn = db.get_connection()
    try:
        conn.execute("DELETE FROM work_records WHERE date = ?", (today,))
        conn.execute(
            "INSERT INTO work_records (date, clock_in, clock_out, lunch_break, dinner_break) VALUES (?, ?, ?, ?, ?)",
            (today, '09:00:00', '18:00:00', 0, 0)
        )
        conn.commit()
    finally:
        conn.close()
    w = MainWindow(db=db)
    # 기본 상태
    assert w.is_clocked_in == False  # 퇴근 완료 기록이므로 False
    assert w.lunch_break_enabled == False
    # auto_lunch 캐시 초기 None (AutoLunchManager 낶)
    assert w._auto_lunch._enabled_cache is None
    # 단축키 7개 등록되었는지
    from PyQt5.QtWidgets import QShortcut
    shortcuts = w.findChildren(QShortcut)
    assert len(shortcuts) >= 7, f"shortcuts: {len(shortcuts)}"
    w.deleteLater()


def test_settings_save_load_round_trip():
    """설정 저장→로드 라운드트립"""
    from ui.settings_view import SettingsView
    dlg = SettingsView(db=db)
    # 단축근무 프리셋 → 저장
    dlg.work_preset_combo.setCurrentIndex(1)
    # save 호출 시 메시지박스가 뜨므로 save_settings 직접 호출 회피
    # 대신 저장 로직과 동일한 dict 만들기
    work_min = dlg.work_hours_spin.value() * 60 + dlg.work_minutes_spin.value()
    db.save_settings({
        'work_minutes': work_min,
        'lunch_duration_minutes': dlg.lunch_spin.value(),
    })
    # 새 다이얼로그에 다시 로드
    dlg2 = SettingsView(db=db)
    assert dlg2.work_hours_spin.value() == 7
    assert dlg2.work_minutes_spin.value() == 30
    assert dlg2.lunch_spin.value() == 30
    # 프리셋이 자동 매칭되었는지
    assert dlg2.work_preset_combo.currentIndex() == 1
    dlg.deleteLater()
    dlg2.deleteLater()


# 실행
case("UI-1. SettingsView: 단축근무 프리셋 적용", test_settings_view)
case("UI-2. HelpView: 6개 탭 생성 확인", test_help_view)
case("UI-3. MiniWidget: 시간 업데이트 + 추가근무 표시", test_mini_widget)
case("UI-4. ChartWidget: 빈/유효 데이터 그리기", test_chart_widget)
case("UI-5. StatsView: 데이터 없이 로드", test_stats_view)
case("UI-6. CalendarView: 인스턴스화", test_calendar_view)
case("UI-7. MainWindow: 단축키 7개 등록 + 초기 상태", test_main_window_init)
case("UI-8. Settings 저장→재로드: 단축근무 7h30m round-trip", test_settings_save_load_round_trip)

print()
print("=" * 60)
print(f"PASS: {len(PASS)}  FAIL: {len(FAIL)}")
if FAIL:
    print("\nFAILED:")
    for label, err in FAIL:
        print(f"  - {label}: {err}")

# Cleanup
if os.path.exists(db_path):
    try: os.remove(db_path)
    except: pass

sys.exit(1 if FAIL else 0)
