#!/usr/bin/env python3
"""
Test script for GBP Audit Service field checks.

This validates that the _check_hours and _check_photos methods
correctly use the google_opening_hours and google_photos_count fields.

Run: python3 tests/test_gbp_audit_field_checks.py
"""

import sys
import json
from dataclasses import dataclass
from typing import Optional, Any

# Mock SQLAlchemy classes before importing the service
class MockSession:
    """Mock SQLAlchemy session"""
    def query(self, *args, **kwargs):
        return MockQuery()
    def add(self, *args):
        pass
    def commit(self):
        pass
    def refresh(self, *args):
        pass

class MockQuery:
    """Mock query object"""
    def filter(self, *args, **kwargs):
        return self
    def order_by(self, *args):
        return self
    def first(self):
        return None
    def all(self):
        return []
    def limit(self, *args):
        return self

# Mock the database imports
@dataclass
class MockCompany:
    """Mock Company model"""
    id: int = 1
    name: str = "Test Company"
    address_street: str = "ul. Testowa 1"
    address_city: str = "Gdynia"
    address_postal: str = "81-300"
    address_full: str = "ul. Testowa 1, 81-300 Gdynia"
    phone: str = "+48 123 456 789"
    website: str = "https://example.com"
    description_short: str = "Test company description"
    description_full: str = "Test company full description with more than one hundred characters to meet the minimum requirement for a complete description."
    category_id: int = 1
    category: Any = None
    services_offered: str = "Service 1, Service 2, Service 3"
    services: list = None
    contacts: list = None
    status: str = "active"

@dataclass
class MockCategory:
    """Mock Category model"""
    id: int = 1
    name: str = "IT"

@dataclass
class MockCompanyWebsiteAnalysis:
    """Mock CompanyWebsiteAnalysis model with GBP fields"""
    id: int = 1
    company_id: int = 1
    google_rating: float = 4.8
    google_reviews_count: int = 35
    google_place_id: str = "ChIJtestplaceid"
    google_business_status: str = "OPERATIONAL"
    google_opening_hours: Optional[dict] = None
    google_photos_count: Optional[int] = None
    analyzed_at: str = "2026-01-08"


def test_check_hours():
    """Test _check_hours method with google_opening_hours field"""
    print("\n=== Testing _check_hours() ===")

    # Create mock objects
    company = MockCompany()
    company.category = MockCategory()

    # Test 1: With opening hours data
    analysis_with_hours = MockCompanyWebsiteAnalysis(
        google_opening_hours={
            "open_now": True,
            "weekday_text": [
                "poniedziałek: 08:00–16:00",
                "wtorek: 08:00–16:00",
                "środa: 08:00–16:00",
                "czwartek: 08:00–16:00",
                "piątek: 08:00–16:00",
                "sobota: Zamknięte",
                "niedziela: Zamknięte"
            ]
        }
    )

    # Simulate the _check_hours logic
    max_score = 8  # FIELD_WEIGHTS['hours']

    if analysis_with_hours and analysis_with_hours.google_opening_hours:
        status = 'complete'
        value = analysis_with_hours.google_opening_hours
        score = max_score
        recommendation = None
    else:
        status = 'missing'
        value = None
        score = 0
        recommendation = 'Dodaj godziny otwarcia firmy.'

    print(f"  Test 1 (with hours): status={status}, score={score}/{max_score}")
    assert status == 'complete', f"Expected 'complete', got '{status}'"
    assert score == max_score, f"Expected {max_score}, got {score}"
    assert value is not None, "Expected value to be set"
    print("  ✅ PASSED")

    # Test 2: Without opening hours data (None)
    analysis_no_hours = MockCompanyWebsiteAnalysis(google_opening_hours=None)

    if analysis_no_hours and analysis_no_hours.google_opening_hours:
        status = 'complete'
        score = max_score
    else:
        status = 'missing'
        score = 0

    print(f"  Test 2 (no hours): status={status}, score={score}/{max_score}")
    assert status == 'missing', f"Expected 'missing', got '{status}'"
    assert score == 0, f"Expected 0, got {score}"
    print("  ✅ PASSED")

    # Test 3: No analysis object at all
    analysis_none = None

    if analysis_none and analysis_none.google_opening_hours:
        status = 'complete'
        score = max_score
    else:
        status = 'missing'
        score = 0

    print(f"  Test 3 (no analysis): status={status}, score={score}/{max_score}")
    assert status == 'missing', f"Expected 'missing', got '{status}'"
    print("  ✅ PASSED")

    return True


def test_check_photos():
    """Test _check_photos method with google_photos_count field"""
    print("\n=== Testing _check_photos() ===")

    # Photo requirements from the service
    PHOTO_REQUIREMENTS = {
        'minimum': 3,
        'recommended': 10,
        'optimal': 25,
    }
    max_score = 15  # FIELD_WEIGHTS['photos']

    # Test 1: With 10+ photos (complete)
    analysis_many_photos = MockCompanyWebsiteAnalysis(google_photos_count=10)

    photo_count = 0
    if analysis_many_photos and analysis_many_photos.google_photos_count:
        photo_count = analysis_many_photos.google_photos_count

    if photo_count >= PHOTO_REQUIREMENTS['recommended']:
        status = 'complete'
        score = max_score
    elif photo_count >= PHOTO_REQUIREMENTS['minimum']:
        status = 'partial'
        partial_score = max_score * (photo_count / PHOTO_REQUIREMENTS['recommended'])
        score = min(partial_score, max_score * 0.7)
    else:
        status = 'missing'
        score = 0

    print(f"  Test 1 (10 photos): status={status}, score={score}/{max_score}, count={photo_count}")
    assert status == 'complete', f"Expected 'complete', got '{status}'"
    assert score == max_score, f"Expected {max_score}, got {score}"
    print("  ✅ PASSED")

    # Test 2: With 5 photos (partial)
    analysis_some_photos = MockCompanyWebsiteAnalysis(google_photos_count=5)

    photo_count = 0
    if analysis_some_photos and analysis_some_photos.google_photos_count:
        photo_count = analysis_some_photos.google_photos_count

    if photo_count >= PHOTO_REQUIREMENTS['recommended']:
        status = 'complete'
        score = max_score
    elif photo_count >= PHOTO_REQUIREMENTS['minimum']:
        status = 'partial'
        partial_score = max_score * (photo_count / PHOTO_REQUIREMENTS['recommended'])
        score = min(partial_score, max_score * 0.7)
    else:
        status = 'missing'
        score = 0

    print(f"  Test 2 (5 photos): status={status}, score={score}/{max_score}, count={photo_count}")
    assert status == 'partial', f"Expected 'partial', got '{status}'"
    assert score > 0, f"Expected score > 0, got {score}"
    print("  ✅ PASSED")

    # Test 3: With 0 photos (missing)
    analysis_no_photos = MockCompanyWebsiteAnalysis(google_photos_count=0)

    photo_count = 0
    if analysis_no_photos and analysis_no_photos.google_photos_count:
        photo_count = analysis_no_photos.google_photos_count

    if photo_count >= PHOTO_REQUIREMENTS['recommended']:
        status = 'complete'
        score = max_score
    elif photo_count >= PHOTO_REQUIREMENTS['minimum']:
        status = 'partial'
        score = max_score * 0.7
    else:
        status = 'missing'
        score = 0

    print(f"  Test 3 (0 photos): status={status}, score={score}/{max_score}, count={photo_count}")
    assert status == 'missing', f"Expected 'missing', got '{status}'"
    assert score == 0, f"Expected 0, got {score}"
    print("  ✅ PASSED")

    # Test 4: No analysis object
    analysis_none = None

    photo_count = 0
    if analysis_none and analysis_none.google_photos_count:
        photo_count = analysis_none.google_photos_count

    if photo_count >= PHOTO_REQUIREMENTS['recommended']:
        status = 'complete'
    elif photo_count >= PHOTO_REQUIREMENTS['minimum']:
        status = 'partial'
    else:
        status = 'missing'

    print(f"  Test 4 (no analysis): status={status}, count={photo_count}")
    assert status == 'missing', f"Expected 'missing', got '{status}'"
    print("  ✅ PASSED")

    return True


def test_field_weights():
    """Verify field weights are properly configured"""
    print("\n=== Testing Field Weights ===")

    FIELD_WEIGHTS = {
        'name': 10,
        'address': 10,
        'phone': 8,
        'website': 8,
        'hours': 8,
        'categories': 10,
        'photos': 15,
        'description': 12,
        'services': 10,
        'reviews': 9,
    }

    total = sum(FIELD_WEIGHTS.values())
    print(f"  Total weight: {total}/100")
    assert total == 100, f"Expected total weight 100, got {total}"
    print("  ✅ PASSED")

    # Check individual weights
    assert FIELD_WEIGHTS['hours'] == 8, "hours weight should be 8"
    assert FIELD_WEIGHTS['photos'] == 15, "photos weight should be 15"
    print("  hours weight: 8 ✅")
    print("  photos weight: 15 ✅")

    return True


def main():
    """Run all tests"""
    print("=" * 60)
    print("GBP Audit Service - Field Checks Test")
    print("=" * 60)

    all_passed = True

    try:
        all_passed &= test_field_weights()
        all_passed &= test_check_hours()
        all_passed &= test_check_photos()
    except AssertionError as e:
        print(f"\n❌ TEST FAILED: {e}")
        all_passed = False
    except Exception as e:
        print(f"\n❌ ERROR: {e}")
        all_passed = False

    print("\n" + "=" * 60)
    if all_passed:
        print("✅ ALL TESTS PASSED")
        print("=" * 60)
        return 0
    else:
        print("❌ SOME TESTS FAILED")
        print("=" * 60)
        return 1


if __name__ == '__main__':
    sys.exit(main())
