# Test Verification Suite for Technical Roadmap 22_CLIENT_DESK.md
import os
import pytest
import numpy as np
from fastapi import HTTPException

from app.core.dsp_utils import find_zero_crossing, apply_micro_crossfade
from app.core.vst_engine import render_midi_events_to_audio
from app.api.v1.auth import enforce_password_changed

def test_kpi_1_zero_crossing_detection():
    """Kiểm thử Zero-Crossing: Cắt lát nhạc bằng AI Cut ở mốc giây lẻ (22_CLIENT_DESK.md §5)."""
    sr = 44100
    # Generate 1 second sine wave at 440 Hz
    t = np.linspace(0, 1.0, sr)
    signal = np.sin(2 * np.pi * 440 * t)

    target_time = 0.1234  # Odd time offset
    zc_time = find_zero_crossing(signal, sr, target_time, window_seconds=0.04)

    assert zc_time is not None
    zc_sample = int(zc_time * sr)
    # Verify physical sign inversion x[i] * x[i+1] <= 0
    if 0 <= zc_sample < len(signal) - 1:
        assert signal[zc_sample] * signal[zc_sample + 1] <= 0.05
    print(f"Zero crossing test passed: target {target_time}s -> zc {zc_time}s")

def test_kpi_2_micro_crossfade_splicing():
    """Kiểm thử Micro-Crossfade (10ms) tại hai đầu điểm ráp nối để triệt tiêu click/pop."""
    sr = 44100
    original = np.ones(sr, dtype=np.float32) * 0.5
    edited = np.ones(sr // 2, dtype=np.float32) * 0.8
    start_sample = sr // 4

    output = apply_micro_crossfade(original, edited, start_sample, fade_len_ms=10, sr=sr)
    assert len(output) == len(original)
    # Check smooth transition at start
    assert 0.49 <= output[start_sample] <= 0.81
    print("Micro-crossfade splicing test passed.")

def test_kpi_3_vst_synth_midi_rendering():
    """Kiểm thử Docker VSTi: Gửi chuỗi MIDI nốt và nạp synth tổng hợp ra mảng Stereo."""
    midi_events = [
        {"note": 60, "start_beat": 0.0, "duration_beats": 1.0, "velocity": 100}, # C4
        {"note": 64, "start_beat": 1.0, "duration_beats": 1.0, "velocity": 90},  # E4
        {"note": 67, "start_beat": 2.0, "duration_beats": 2.0, "velocity": 110}  # G4
    ]

    audio_array = render_midi_events_to_audio(midi_events, sr=44100, bpm=120.0)

    assert isinstance(audio_array, np.ndarray)
    assert audio_array.shape[0] == 2  # Stereo channels (L, R)
    assert audio_array.shape[1] > 0
    assert np.max(np.abs(audio_array)) > 0.01
    print(f"VSTi MIDI rendering test passed: stereo output shape {audio_array.shape}")

def test_kpi_4_auth_security_must_change_password():
    """Kiểm thử Bảo Mật Auth: Đăng nhập tài khoản mặc định và gọi API (22_CLIENT_DESK.md §5)."""
    user_must_change = {"user_id": "test_user_1", "must_change_password": True}
    user_password_changed = {"user_id": "test_user_2", "must_change_password": False}

    # Should raise HTTP 403 Forbidden when must_change_password = True
    with pytest.raises(HTTPException) as exc_info:
        enforce_password_changed(user_must_change)
    assert exc_info.value.status_code == 403

    # Should pass without error when must_change_password = False
    enforce_password_changed(user_password_changed)
    print("Auth Security 403 Forbidden test passed.")

def test_kpi_5_storage_quota_calculation():
    """Kiểm thử Quota: S_used + S_new <= S_limit."""
    s_limit_mb = 500
    s_used_mb = 480
    s_new_mb = 30  # Total = 510MB > 500MB limit

    total = s_used_mb + s_new_mb
    is_quota_exceeded = total > s_limit_mb

    assert is_quota_exceeded is True
    print("Storage Quota calculation test passed.")

def test_kpi_6_shift_click_range_anchor_math():
    """Kiểm thử Shift+Click: Bôi chọn cục bộ [min(T_anchor, T_end), max(T_anchor, T_end)]."""
    t_anchor = 5.4
    t_end = 2.1

    sel_start = min(t_anchor, t_end)
    sel_end = max(t_anchor, t_end)

    assert sel_start == 2.1
    assert sel_end == 5.4
    print("Shift+Click range anchor math test passed.")
