"""
Test script for RateLoader Phase 5 implementation.

Tests the rate_loader_logic.py and http_server.py components.
"""

import json
import time
import requests
import threading
from typing import Dict, Any

from core.http_server import start_server, stop_server, is_server_running
from core.config import get_config
from core.logger import get_rateloader_logger
from features.rate_loader_logic import build_plsql, process_prices, parse_json_data


def test_build_plsql():
    """Test the build_plsql function with various scenarios."""
    print("Testing build_plsql function...")
    logger = get_rateloader_logger()
    
    # Test case 1: Single price with guests == 1 (should generate double putrate)
    prices = [
        {
            "date": "2024-01-01",
            "category": "STD",
            "ratecode": "RACK",
            "price": 100.50,
            "guests": 1,
            "children_rates": []
        }
    ]
    
    plsql = build_plsql(prices)
    expected_lines = [
        "m_rlputrate(to_date('2024-01-01', 'yyyy-mm-dd'), 'STD', 'RACK', 100.5, 0);",
        "m_rlputrate(to_date('2024-01-01', 'yyyy-mm-dd'), 'STD', 'RACK', 100.5, 1);"
    ]
    
    for line in expected_lines:
        if line not in plsql:
            print(f"❌ FAIL: Expected line not found in PL/SQL: {line}")
            return False
    
    # Test case 2: Single price with guests == 2 (should generate single putrate)
    prices = [
        {
            "date": "2024-01-02",
            "category": "DELUXE",
            "ratecode": "CORP",
            "price": 150.75,
            "guests": 2,
            "children_rates": []
        }
    ]
    
    plsql = build_plsql(prices)
    expected_line = "m_rlputrate(to_date('2024-01-02', 'yyyy-mm-dd'), 'DELUXE', 'CORP', 150.75, 2);"
    
    if expected_line not in plsql:
        print(f"❌ FAIL: Expected line not found in PL/SQL: {expected_line}")
        return False
    
    # Test case 3: Price with children rates
    prices = [
        {
            "date": "2024-01-03",
            "category": "SUITE",
            "ratecode": "VIP",
            "price": 250.00,
            "guests": 2,
            "children_rates": [
                {"price": 50.00, "age_category": "child"},
                {"price": 75.00, "age_category": "teen"}
            ]
        }
    ]
    
    plsql = build_plsql(prices)
    expected_lines = [
        "m_rlputrate(to_date('2024-01-03', 'yyyy-mm-dd'), 'SUITE', 'VIP', 250.0, 2);",
        "m_rladdchild(to_date('2024-01-03', 'yyyy-mm-dd'), 'SUITE', 'VIP', 50.0, 'child');",
        "m_rladdchild(to_date('2024-01-03', 'yyyy-mm-dd'), 'SUITE', 'VIP', 75.0, 'teen');"
    ]
    
    for line in expected_lines:
        if line not in plsql:
            print(f"❌ FAIL: Expected line not found in PL/SQL: {line}")
            return False
    
    print("✅ build_plsql function tests passed")
    return True


def test_parse_json_data():
    """Test the parse_json_data function."""
    print("Testing parse_json_data function...")
    
    # Test valid JSON
    valid_json = '{"prices": [{"date": "2024-01-01", "category": "STD", "ratecode": "RACK", "price": 100.0, "guests": 1}]}'
    data = parse_json_data(valid_json)
    
    if data is None or "prices" not in data:
        print("❌ FAIL: Valid JSON parsing failed")
        return False
    
    # Test invalid JSON
    invalid_json = '{"prices": [invalid json]}'
    data = parse_json_data(invalid_json)
    
    if data is not None:
        print("❌ FAIL: Invalid JSON should return None")
        return False
    
    print("✅ parse_json_data function tests passed")
    return True


def test_http_server():
    """Test the HTTP server endpoints."""
    print("Testing HTTP server...")
    logger = get_rateloader_logger()
    
    # Get server port from config
    config = get_config()
    port = config.get_int("server_port", fallback=8000)
    base_url = f"http://localhost:{port}"
    print(f"Testing HTTP server on port {port}...")
    
    # Start server
    if not start_server():
        print("❌ FAIL: Failed to start HTTP server")
        return False
    
    # Wait for server to start
    time.sleep(1)
    
    if not is_server_running():
        print("❌ FAIL: Server is not running after start")
        return False
    
    try:
        # Test GET /ping
        print("Testing GET /ping...")
        response = requests.get(f"{base_url}/ping", timeout=5)
        if response.status_code != 200:
            print(f"❌ FAIL: GET /ping returned status {response.status_code}")
            return False
        
        data = response.json()
        if data.get("status") != "ok":
            print(f"❌ FAIL: GET /ping returned unexpected response: {data}")
            return False
        
        print("✅ GET /ping test passed")
        
        # Test GET /status
        print("Testing GET /status...")
        response = requests.get(f"{base_url}/status", timeout=5)
        if response.status_code != 200:
            print(f"❌ FAIL: GET /status returned status {response.status_code}")
            return False
        
        data = response.json()
        if "server" not in data or "timestamp" not in data:
            print(f"❌ FAIL: GET /status returned unexpected response: {data}")
            return False
        
        print("✅ GET /status test passed")
        
        # Test POST /load with valid JSON
        print("Testing POST /load...")
        test_data = {
            "prices": [
                {
                    "date": "2024-01-01",
                    "category": "STD",
                    "ratecode": "RACK",
                    "price": 100.50,
                    "guests": 1,
                    "children_rates": [
                        {"price": 25.00, "age_category": "child"}
                    ]
                }
            ]
        }
        
        response = requests.post(
            f"{base_url}/load",
            json=test_data,
            headers={'Content-Type': 'application/json'},
            timeout=5
        )
        
        if response.status_code != 200:
            print(f"❌ FAIL: POST /load returned status {response.status_code}")
            return False
        
        expected_response = "POST request for /load"
        if response.text != expected_response:
            print(f"❌ FAIL: POST /load returned unexpected response: {response.text}")
            return False
        
        print("✅ POST /load test passed")
        
        # Test POST /load with invalid JSON
        print("Testing POST /load with invalid JSON...")
        response = requests.post(
            f"{base_url}/load",
            data="invalid json",
            headers={'Content-Type': 'application/json'},
            timeout=5
        )
        
        if response.status_code != 400:
            print(f"❌ FAIL: POST /load with invalid JSON should return 400, got {response.status_code}")
            return False
        
        print("✅ POST /load with invalid JSON test passed")
        
        # Test 404 for unknown endpoint
        print("Testing 404 for unknown endpoint...")
        response = requests.get(f"{base_url}/unknown", timeout=5)
        if response.status_code != 404:
            print(f"❌ FAIL: Unknown endpoint should return 404, got {response.status_code}")
            return False
        
        print("✅ 404 test passed")
        
        return True
        
    except requests.RequestException as e:
        print(f"❌ FAIL: HTTP request error: {str(e)}")
        return False
    finally:
        # Stop server
        if not stop_server():
            print("❌ FAIL: Failed to stop HTTP server")
            return False
        
        # Wait for server to stop
        time.sleep(1)


def run_all_tests():
    """Run all tests."""
    print("=" * 50)
    print("Running RateLoader Phase 5 Tests")
    print("=" * 50)
    
    tests = [
        test_build_plsql,
        test_parse_json_data,
        test_http_server
    ]
    
    passed = 0
    total = len(tests)
    
    for test in tests:
        try:
            if test():
                passed += 1
            print()
        except Exception as e:
            print(f"❌ FAIL: Test {test.__name__} threw exception: {str(e)}")
            print()
    
    print("=" * 50)
    print(f"Test Results: {passed}/{total} tests passed")
    print("=" * 50)
    
    if passed == total:
        print("🎉 All tests passed! Phase 5 implementation is working correctly.")
        return True
    else:
        print("❌ Some tests failed. Please check the implementation.")
        return False


if __name__ == "__main__":
    run_all_tests()