import pytest
import numpy as np
import os
import app.api.v1.user_config as user_config
user_config.DATA_FILE = os.path.join(os.path.dirname(__file__), "user_configs_test.json")

from fastapi.testclient import TestClient
from app.main import app
from app.core.ai_dsp_engine import AIDSPEngine
from app.core.python_tools_engine import PythonToolsEngine

client = TestClient(app)

def test_find_exact_zero_crossing():
    # Create sine wave audio signal: 441 Hz at 44100 Hz sample rate (100 samples per cycle)
    sr = 44100
    t = np.linspace(0, 1.0, sr, endpoint=False)
    y = np.sin(2 * np.pi * 441 * t)
    
    # Target time = 0.052 seconds
    target_time = 0.052
    z_time = AIDSPEngine.find_exact_zero_crossing(y, sr, target_time, window_ms=50.0)
    
    # Verify zero crossing condition: y[sample] * y[sample+1] <= 0
    sample_idx = int(z_time * sr)
    if sample_idx < len(y) - 1:
        assert y[sample_idx] * y[sample_idx + 1] <= 0 or abs(y[sample_idx]) < 1e-3

def test_scan_best_loop_regions():
    sr = 44100
    t = np.linspace(0, 5.0, sr * 5, endpoint=False)
    y = np.sin(2 * np.pi * 440 * t)
    
    loops = AIDSPEngine.scan_best_loop_regions(y, sr, min_duration=2.0, max_duration=4.0)
    assert len(loops) > 0
    assert "start_time" in loops[0]
    assert "end_time" in loops[0]
    assert loops[0]["end_time"] > loops[0]["start_time"]

def test_slice_and_copy_with_zero_crossing():
    sr = 44100
    t = np.linspace(0, 4.0, sr * 4, endpoint=False)
    y = np.sin(2 * np.pi * 440 * t)
    
    sliced, z_start, z_end = AIDSPEngine.slice_and_copy_with_zero_crossing(y, sr, 1.0, 3.0)
    assert len(sliced) > 0
    assert z_end > z_start

def test_python_tools_engine():
    sr = 44100
    y = np.array([0.1, -0.5, 0.8, -0.2], dtype=np.float32)
    
    # 1. Normalize
    norm = PythonToolsEngine.normalize_peak(y, target_db=0.0)
    assert pytest.approx(np.max(np.abs(norm)), rel=1e-3) == 1.0
    
    # 2. Phase Invert
    inv = PythonToolsEngine.invert_phase(y)
    assert np.allclose(inv, -y)
    
    # 3. Swap Channels
    stereo = np.array([[0.1, 0.2], [0.8, 0.9]])
    swapped = PythonToolsEngine.swap_channels(stereo)
    assert np.allclose(swapped[0], stereo[1])
    
    # 4. Synth Wave Generator
    sine = PythonToolsEngine.generate_synth_wave("sine", 440.0, 1.0, sr)
    assert len(sine) == sr

def test_api_ai_scan():
    res = client.post('/api/v1/audio/ai-scan', json={
        "track_id": "1",
        "min_loop_duration": 2.0,
        "max_loop_duration": 6.0
    })
    assert res.status_code == 200
    data = res.json()
    assert data["success"] is True
    assert len(data["suggested_loops"]) > 0

def test_api_ai_cut():
    res = client.post('/api/v1/audio/ai-cut', json={
        "source_track_id": "1",
        "selection_start": 1.0,
        "selection_end": 3.0
    })
    assert res.status_code == 200
    data = res.json()
    assert data["success"] is True
    assert "aligned_start" in data
    assert "aligned_end" in data

def test_api_user_ai_config():
    # GET
    res_get = client.get('/api/v1/user/config/ai')
    assert res_get.status_code == 200
    providers = res_get.json()["providers"]
    assert len(providers) > 0
    
    # POST
    providers[0]["api_key"] = "test-sk-key-123"
    res_post = client.post('/api/v1/user/config/ai', json={"providers": providers})
    assert res_post.status_code == 200
    assert res_post.json()["success"] is True
