#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
認證 API 測試

Author: PANJIT IT Team
Created: 2024-01-28
Modified: 2024-01-28
"""

import pytest
from unittest.mock import patch, MagicMock
from app.models.user import User


class TestAuthAPI:
    """認證 API 測試類別"""
    
    def test_login_success(self, client, mock_ldap_response):
        """測試成功登入"""
        with patch('app.utils.ldap_auth.LDAPAuthService.authenticate_user') as mock_auth:
            mock_auth.return_value = mock_ldap_response
            
            response = client.post('/api/v1/auth/login', json={
                'username': 'testuser@panjit.com.tw',
                'password': 'password123'
            })
            
            assert response.status_code == 200
            data = response.get_json()
            assert data['success'] is True
            assert 'user' in data['data']
            assert data['data']['user']['username'] == 'testuser'
    
    def test_login_invalid_credentials(self, client):
        """測試無效憑證登入"""
        with patch('app.utils.ldap_auth.LDAPAuthService.authenticate_user') as mock_auth:
            mock_auth.side_effect = Exception("認證失敗")
            
            response = client.post('/api/v1/auth/login', json={
                'username': 'testuser@panjit.com.tw',
                'password': 'wrong_password'
            })
            
            assert response.status_code == 401
            data = response.get_json()
            assert data['success'] is False
            assert data['error'] == 'INVALID_CREDENTIALS'
    
    def test_login_missing_fields(self, client):
        """測試缺少必要欄位"""
        response = client.post('/api/v1/auth/login', json={
            'username': 'testuser@panjit.com.tw'
            # 缺少 password
        })
        
        assert response.status_code == 400
        data = response.get_json()
        assert data['success'] is False
        assert 'MISSING_FIELDS' in data['error']
    
    def test_login_empty_credentials(self, client):
        """測試空的認證資訊"""
        response = client.post('/api/v1/auth/login', json={
            'username': '',
            'password': ''
        })
        
        assert response.status_code == 400
        data = response.get_json()
        assert data['success'] is False
        assert data['error'] == 'INVALID_INPUT'
    
    def test_logout_success(self, authenticated_client):
        """測試成功登出"""
        response = authenticated_client.post('/api/v1/auth/logout')
        
        assert response.status_code == 200
        data = response.get_json()
        assert data['success'] is True
        assert data['message'] == '登出成功'
    
    def test_logout_without_login(self, client):
        """測試未登入時登出"""
        response = client.post('/api/v1/auth/logout')
        
        assert response.status_code == 401
        data = response.get_json()
        assert data['success'] is False
        assert data['error'] == 'AUTHENTICATION_REQUIRED'
    
    def test_get_current_user_success(self, authenticated_client, auth_user):
        """測試取得當前使用者資訊"""
        response = authenticated_client.get('/api/v1/auth/me')
        
        assert response.status_code == 200
        data = response.get_json()
        assert data['success'] is True
        assert 'user' in data['data']
        assert data['data']['user']['id'] == auth_user.id
    
    def test_get_current_user_without_login(self, client):
        """測試未登入時取得使用者資訊"""
        response = client.get('/api/v1/auth/me')
        
        assert response.status_code == 401
        data = response.get_json()
        assert data['success'] is False
        assert data['error'] == 'AUTHENTICATION_REQUIRED'
    
    def test_check_auth_valid(self, authenticated_client, auth_user):
        """測試檢查有效認證狀態"""
        response = authenticated_client.get('/api/v1/auth/check')
        
        assert response.status_code == 200
        data = response.get_json()
        assert data['success'] is True
        assert data['authenticated'] is True
    
    def test_check_auth_invalid(self, client):
        """測試檢查無效認證狀態"""
        response = client.get('/api/v1/auth/check')
        
        assert response.status_code == 401
        data = response.get_json()
        assert data['success'] is False
        assert data['authenticated'] is False
    
    def test_refresh_session_success(self, authenticated_client, auth_user):
        """測試刷新 Session"""
        response = authenticated_client.post('/api/v1/auth/refresh')
        
        assert response.status_code == 200
        data = response.get_json()
        assert data['success'] is True
        assert data['data']['session_refreshed'] is True
    
    def test_refresh_session_without_login(self, client):
        """測試未登入時刷新 Session"""
        response = client.post('/api/v1/auth/refresh')
        
        assert response.status_code == 401
        data = response.get_json()
        assert data['success'] is False
        assert data['error'] == 'AUTHENTICATION_REQUIRED'
    
    def test_search_users_success(self, authenticated_client):
        """測試搜尋使用者"""
        with patch('app.utils.ldap_auth.LDAPAuthService.search_users') as mock_search:
            mock_search.return_value = [
                {
                    'username': 'user1',
                    'display_name': 'User One',
                    'email': 'user1@panjit.com.tw',
                    'department': 'IT'
                },
                {
                    'username': 'user2',
                    'display_name': 'User Two',
                    'email': 'user2@panjit.com.tw',
                    'department': 'HR'
                }
            ]
            
            response = authenticated_client.get('/api/v1/auth/search-users?q=user')
            
            assert response.status_code == 200
            data = response.get_json()
            assert data['success'] is True
            assert len(data['data']['users']) == 2
    
    def test_search_users_short_term(self, authenticated_client):
        """測試搜尋關鍵字太短"""
        response = authenticated_client.get('/api/v1/auth/search-users?q=u')
        
        assert response.status_code == 400
        data = response.get_json()
        assert data['success'] is False
        assert data['error'] == 'INVALID_SEARCH_TERM'
    
    def test_search_users_without_login(self, client):
        """測試未登入時搜尋使用者"""
        response = client.get('/api/v1/auth/search-users?q=user')
        
        assert response.status_code == 401
        data = response.get_json()
        assert data['success'] is False
        assert data['error'] == 'AUTHENTICATION_REQUIRED'
    
    def test_admin_access_with_admin(self, admin_client, admin_user):
        """測試管理員存取管理功能"""
        response = admin_client.get('/api/v1/admin/stats')
        
        # 這個測試會因為沒有實際資料而可能失敗，但應該通過認證檢查
        # 狀態碼應該是 200 或其他非認證錯誤
        assert response.status_code != 401
        assert response.status_code != 403
    
    def test_admin_access_without_permission(self, authenticated_client):
        """測試一般使用者存取管理功能"""
        response = authenticated_client.get('/api/v1/admin/stats')
        
        assert response.status_code == 403
        data = response.get_json()
        assert data['success'] is False
        assert data['error'] == 'PERMISSION_DENIED'