import pytest
import pandas as pd
import numpy as np
from mlguardian import DriftDetector, DriftType


class TestDriftDetector:
    def test_no_drift_identical(self):
        df = pd.DataFrame({
            'num': np.random.normal(0, 1, 1000),
            'cat': np.random.choice(['a', 'b', 'c'], 1000)
        })
        
        detector = DriftDetector()
        detector.fit(df)
        
        report = detector.detect(df)
        assert not report.drift_detected

    def test_drift_detected(self):
        np.random.seed(42)  # For reproducibility
        
        ref = pd.DataFrame({
            'num': np.random.normal(0, 1, 1000),
            'cat': np.random.choice(['a', 'b', 'c'], 1000, p=[0.5, 0.3, 0.2])
        })
        
        curr = pd.DataFrame({
            'num': np.random.normal(5, 2, 1000),  # Different distribution
            'cat': np.random.choice(['a', 'b', 'c'], 1000, p=[0.2, 0.3, 0.5])  # Different probs
        })
        
        detector = DriftDetector(threshold=0.05)
        detector.fit(ref)
        
        report = detector.detect(curr)
        
        # Check if drift was detected
        assert report.drift_detected, "Drift should be detected"
        # Check details contain drifted columns
        assert 'drifted_columns' in report.details, "Details should contain drifted_columns"
        assert len(report.details['drifted_columns']) > 0, "Should have drifted columns"

    def test_concept_drift(self):
        # Feature stays same, but target relationship changes
        np.random.seed(42)
        X_ref = pd.DataFrame({'x': np.random.normal(0, 1, 500)})
        y_ref = (X_ref['x'] > 0).astype(int)
        
        X_curr = pd.DataFrame({'x': np.random.normal(0, 1, 500)})
        y_curr = (X_curr['x'] < 0).astype(int)  # Flipped relationship
        
        detector = DriftDetector()
        detector.fit(X_ref, y_ref)
        
        report = detector.detect(X_curr, y_curr)
        # Should detect concept drift through proxy model
        concept_drift = DriftType.CONCEPT_DRIFT in report.drift_type
        score_high = report.details.get('concept_drift_score', 0) > 0
        assert concept_drift or score_high, "Should detect concept drift"