import pytest
from app import create_app, db
from app.models import User, Project, TimeEntry
from datetime import datetime, timedelta
from flask_login import login_user

@pytest.fixture
def app():
    app = create_app()
    app.config['TESTING'] = True
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
    
    with app.app_context():
        db.create_all()
        yield app
        db.drop_all()

@pytest.fixture
def client(app):
    return app.test_client()

@pytest.fixture
def sample_data(app):
    with app.app_context():
        # Create test user
        user = User(username='testuser', role='user')
        user.is_active = True
        db.session.add(user)
        
        # Create test project
        project = Project(name='Test Project', client='Test Client')
        db.session.add(project)
        
        db.session.commit()
        
        # Create test time entries
        base_time = datetime.now() - timedelta(days=5)
        for i in range(5):
            entry = TimeEntry(
                user_id=user.id,
                project_id=project.id,
                start_time=base_time + timedelta(days=i),
                end_time=base_time + timedelta(days=i, hours=8),
                duration_seconds=28800,  # 8 hours
                billable=True
            )
            db.session.add(entry)
        
        db.session.commit()
        
        return {'user': user, 'project': project}

def test_analytics_dashboard_requires_login(client):
    """Test that analytics dashboard requires authentication"""
    response = client.get('/analytics')
    assert response.status_code == 302  # Redirect to login

def test_analytics_dashboard_accessible_when_logged_in(client, app, sample_data):
    """Test that analytics dashboard is accessible when logged in"""
    with app.app_context():
        with client.session_transaction() as sess:
            # Simulate login
            user = sample_data['user']
            login_user(user)
            sess['_user_id'] = user.id
        
        response = client.get('/analytics')
        assert response.status_code == 200
        assert b'Analytics Dashboard' in response.data

def test_hours_by_day_api(client, app, sample_data):
    """Test hours by day API endpoint"""
    with app.app_context():
        with client.session_transaction() as sess:
            user = sample_data['user']
            login_user(user)
            sess['_user_id'] = user.id
        
        response = client.get('/api/analytics/hours-by-day?days=7')
        assert response.status_code == 200
        
        data = response.get_json()
        assert 'labels' in data
        assert 'datasets' in data
        assert len(data['datasets']) > 0

def test_hours_by_project_api(client, app, sample_data):
    """Test hours by project API endpoint"""
    with app.app_context():
        with client.session_transaction() as sess:
            user = sample_data['user']
            login_user(user)
            sess['_user_id'] = user.id
        
        response = client.get('/api/analytics/hours-by-project?days=7')
        assert response.status_code == 200
        
        data = response.get_json()
        assert 'labels' in data
        assert 'datasets' in data
        assert len(data['labels']) > 0

def test_billable_vs_nonbillable_api(client, app, sample_data):
    """Test billable vs non-billable API endpoint"""
    with app.app_context():
        with client.session_transaction() as sess:
            user = sample_data['user']
            login_user(user)
            sess['_user_id'] = user.id
        
        response = client.get('/api/analytics/billable-vs-nonbillable?days=7')
        assert response.status_code == 200
        
        data = response.get_json()
        assert 'labels' in data
        assert 'datasets' in data
        assert len(data['labels']) == 2  # Billable and Non-Billable

def test_hours_by_hour_api(client, app, sample_data):
    """Test hours by hour API endpoint"""
    with app.app_context():
        with client.session_transaction() as sess:
            user = sample_data['user']
            login_user(user)
            sess['_user_id'] = user.id
        
        response = client.get('/api/analytics/hours-by-hour?days=7')
        assert response.status_code == 200
        
        data = response.get_json()
        assert 'labels' in data
        assert 'datasets' in data
        assert len(data['labels']) == 24  # 24 hours

def test_weekly_trends_api(client, app, sample_data):
    """Test weekly trends API endpoint"""
    with app.app_context():
        with client.session_transaction() as sess:
            user = sample_data['user']
            login_user(user)
            sess['_user_id'] = user.id
        
        response = client.get('/api/analytics/weekly-trends?weeks=4')
        assert response.status_code == 200
        
        data = response.get_json()
        assert 'labels' in data
        assert 'datasets' in data

def test_project_efficiency_api(client, app, sample_data):
    """Test project efficiency API endpoint"""
    with app.app_context():
        with client.session_transaction() as sess:
            user = sample_data['user']
            login_user(user)
            sess['_user_id'] = user.id
        
        response = client.get('/api/analytics/project-efficiency?days=7')
        assert response.status_code == 200
        
        data = response.get_json()
        assert 'labels' in data
        assert 'datasets' in data

def test_user_performance_api_requires_admin(client, app, sample_data):
    """Test that user performance API requires admin access"""
    with app.app_context():
        with client.session_transaction() as sess:
            user = sample_data['user']
            login_user(user)
            sess['_user_id'] = user.id
        
        response = client.get('/api/analytics/hours-by-user?days=7')
        assert response.status_code == 403  # Forbidden for non-admin users

def test_user_performance_api_accessible_by_admin(client, app, sample_data):
    """Test that user performance API is accessible by admin users"""
    with app.app_context():
        # Make user admin
        user = sample_data['user']
        user.role = 'admin'
        db.session.commit()
        
        with client.session_transaction() as sess:
            login_user(user)
            sess['_user_id'] = user.id
        
        response = client.get('/api/analytics/hours-by-user?days=7')
        assert response.status_code == 200
        
        data = response.get_json()
        assert 'labels' in data
        assert 'datasets' in data

def test_api_endpoints_with_invalid_parameters(client, app, sample_data):
    """Test API endpoints with invalid parameters"""
    with app.app_context():
        with client.session_transaction() as sess:
            user = sample_data['user']
            login_user(user)
            sess['_user_id'] = user.id
        
        # Test with invalid days parameter
        response = client.get('/api/analytics/hours-by-day?days=invalid')
        assert response.status_code == 500  # Should handle invalid parameter gracefully
        
        # Test with missing parameter (should use default)
        response = client.get('/api/analytics/hours-by-day')
        assert response.status_code == 200
