#!/usr/bin/env python3
"""
Test script for /admin/seo dashboard functionality.

Tests:
1. Dashboard rendering with companies and SEO data
2. Sorting logic (by score, name, date)
3. Filtering logic (by category, score range, search)
4. Drill-down links to company profiles
5. Statistics calculation

Usage:
    python3 tests/test_admin_seo_dashboard.py

    # Uses DATABASE_URL from .env (PostgreSQL via Docker: localhost:5433)
"""

import os
import sys
from datetime import datetime, timedelta

# Add project root to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

# Load .env if dotenv available
try:
    from dotenv import load_dotenv
    load_dotenv()
except ImportError:
    pass

os.environ.setdefault('DATABASE_URL', 'postgresql://nordabiz_app:dev_password@localhost:5433/nordabiz')

from database import SessionLocal, Company, CompanyWebsiteAnalysis, User


def test_dashboard_data_query():
    """Test that the dashboard query returns correct data structure."""
    print("\n=== Test 1: Dashboard Data Query ===")

    db = SessionLocal()
    try:
        # Simulate the admin_seo route query
        companies_query = db.query(
            Company.id,
            Company.name,
            Company.slug,
            Company.website,
            Company.category_id,
            CompanyWebsiteAnalysis.pagespeed_seo_score,
            CompanyWebsiteAnalysis.pagespeed_performance_score,
            CompanyWebsiteAnalysis.pagespeed_accessibility_score,
            CompanyWebsiteAnalysis.pagespeed_best_practices_score,
            CompanyWebsiteAnalysis.seo_audited_at
        ).outerjoin(
            CompanyWebsiteAnalysis,
            Company.id == CompanyWebsiteAnalysis.company_id
        ).filter(
            Company.status == 'active'
        ).order_by(
            Company.name
        ).all()

        print(f"  Total companies returned: {len(companies_query)}")

        # Build companies list
        companies = []
        for row in companies_query:
            company_data = {
                'id': row[0],
                'name': row[1],
                'slug': row[2],
                'website': row[3],
                'category_id': row[4],
                'seo_score': row[5],
                'performance_score': row[6],
                'accessibility_score': row[7],
                'best_practices_score': row[8],
                'seo_audited_at': row[9]
            }
            companies.append(company_data)

        # Verify data structure
        assert len(companies) > 0, "Should have at least one company"

        companies_with_seo = [c for c in companies if c['seo_audited_at'] is not None]
        print(f"  Companies with SEO data: {len(companies_with_seo)}")

        for c in companies[:3]:
            print(f"    - {c['name']}: SEO={c['seo_score']}, audited={c['seo_audited_at']}")

        print("  ✓ Dashboard data query: PASSED")
        return True

    except Exception as e:
        print(f"  ✗ Dashboard data query: FAILED - {e}")
        return False
    finally:
        db.close()


def test_statistics_calculation():
    """Test statistics calculation for the dashboard."""
    print("\n=== Test 2: Statistics Calculation ===")

    db = SessionLocal()
    try:
        # Get SEO data
        companies_query = db.query(
            Company.id,
            CompanyWebsiteAnalysis.pagespeed_seo_score,
            CompanyWebsiteAnalysis.seo_audited_at
        ).outerjoin(
            CompanyWebsiteAnalysis,
            Company.id == CompanyWebsiteAnalysis.company_id
        ).filter(
            Company.status == 'active'
        ).all()

        # Calculate statistics like admin_seo route
        good_count = 0  # 90-100
        medium_count = 0  # 50-89
        poor_count = 0  # 0-49
        not_audited_count = 0
        scores = []

        for row in companies_query:
            score = row[1]
            audited = row[2]

            if audited is None or score is None:
                not_audited_count += 1
            elif score >= 90:
                good_count += 1
                scores.append(score)
            elif score >= 50:
                medium_count += 1
                scores.append(score)
            else:
                poor_count += 1
                scores.append(score)

        avg_score = round(sum(scores) / len(scores)) if scores else None

        print(f"  Good (90-100): {good_count}")
        print(f"  Medium (50-89): {medium_count}")
        print(f"  Poor (0-49): {poor_count}")
        print(f"  Not audited: {not_audited_count}")
        print(f"  Average score: {avg_score}")

        # Verify calculation
        total = good_count + medium_count + poor_count + not_audited_count
        assert total == len(companies_query), "Statistics should sum to total companies"

        print("  ✓ Statistics calculation: PASSED")
        return True

    except Exception as e:
        print(f"  ✗ Statistics calculation: FAILED - {e}")
        return False
    finally:
        db.close()


def test_score_color_coding():
    """Test score color coding logic (green/yellow/red)."""
    print("\n=== Test 3: Score Color Coding ===")

    def get_score_class(score):
        if score is None:
            return 'score-na'
        elif score >= 90:
            return 'score-good'
        elif score >= 50:
            return 'score-medium'
        else:
            return 'score-poor'

    test_cases = [
        (100, 'score-good'),
        (95, 'score-good'),
        (90, 'score-good'),
        (89, 'score-medium'),
        (75, 'score-medium'),
        (50, 'score-medium'),
        (49, 'score-poor'),
        (25, 'score-poor'),
        (0, 'score-poor'),
        (None, 'score-na'),
    ]

    all_passed = True
    for score, expected in test_cases:
        result = get_score_class(score)
        status = "✓" if result == expected else "✗"
        if result != expected:
            all_passed = False
        print(f"    {status} Score {score}: {result} (expected {expected})")

    if all_passed:
        print("  ✓ Score color coding: PASSED")
    else:
        print("  ✗ Score color coding: FAILED")

    return all_passed


def test_sorting_logic():
    """Test client-side sorting logic simulation."""
    print("\n=== Test 4: Sorting Logic ===")

    db = SessionLocal()
    try:
        # Get test data
        companies = db.query(
            Company.name,
            CompanyWebsiteAnalysis.pagespeed_seo_score,
            CompanyWebsiteAnalysis.seo_audited_at
        ).outerjoin(
            CompanyWebsiteAnalysis,
            Company.id == CompanyWebsiteAnalysis.company_id
        ).filter(
            Company.status == 'active',
            CompanyWebsiteAnalysis.seo_audited_at != None
        ).all()

        # Test sorting by name
        sorted_by_name = sorted(companies, key=lambda x: x[0].lower())
        print(f"  Sorted by name (first 3): {[c[0] for c in sorted_by_name[:3]]}")

        # Test sorting by score (descending)
        sorted_by_score = sorted(companies, key=lambda x: x[1] if x[1] else -1, reverse=True)
        print(f"  Sorted by score desc (top 3): {[(c[0], c[1]) for c in sorted_by_score[:3]]}")

        # Test sorting by date (newest first)
        sorted_by_date = sorted(companies, key=lambda x: x[2] if x[2] else datetime.min, reverse=True)
        print(f"  Sorted by date desc (first 3): {[(c[0], c[2].strftime('%Y-%m-%d') if c[2] else 'N/A') for c in sorted_by_date[:3]]}")

        print("  ✓ Sorting logic: PASSED")
        return True

    except Exception as e:
        print(f"  ✗ Sorting logic: FAILED - {e}")
        return False
    finally:
        db.close()


def test_filtering_logic():
    """Test filtering logic simulation."""
    print("\n=== Test 5: Filtering Logic ===")

    db = SessionLocal()
    try:
        # Get test data
        companies = db.query(
            Company.name,
            Company.category_id,
            CompanyWebsiteAnalysis.pagespeed_seo_score,
            CompanyWebsiteAnalysis.seo_audited_at
        ).outerjoin(
            CompanyWebsiteAnalysis,
            Company.id == CompanyWebsiteAnalysis.company_id
        ).filter(
            Company.status == 'active'
        ).all()

        # Convert to list of dicts
        data = [{
            'name': c[0],
            'category_id': c[1],
            'score': c[2],
            'audited': c[3]
        } for c in companies]

        # Filter by score range (good: 90-100)
        good_filter = [c for c in data if c['score'] is not None and c['score'] >= 90]
        print(f"  Filter by good score (>=90): {len(good_filter)} companies")

        # Filter by score range (poor: 0-49)
        poor_filter = [c for c in data if c['score'] is not None and c['score'] < 50]
        print(f"  Filter by poor score (<50): {len(poor_filter)} companies")

        # Filter by not audited
        not_audited_filter = [c for c in data if c['audited'] is None]
        print(f"  Filter by not audited: {len(not_audited_filter)} companies")

        # Filter by search text
        search_term = "pix"
        search_filter = [c for c in data if search_term.lower() in c['name'].lower()]
        print(f"  Filter by search '{search_term}': {len(search_filter)} companies - {[c['name'] for c in search_filter]}")

        print("  ✓ Filtering logic: PASSED")
        return True

    except Exception as e:
        print(f"  ✗ Filtering logic: FAILED - {e}")
        return False
    finally:
        db.close()


def test_drill_down_links():
    """Test drill-down links to company profiles."""
    print("\n=== Test 6: Drill-Down Links ===")

    db = SessionLocal()
    try:
        # Get companies with slugs
        companies = db.query(
            Company.name,
            Company.slug
        ).filter(
            Company.status == 'active'
        ).limit(5).all()

        for c in companies:
            # Verify slug format (should be kebab-case, no special chars)
            expected_url = f"/company/{c[1]}"
            print(f"    {c[0]}: {expected_url}")

            # Verify slug exists and is valid
            assert c[1] is not None, f"Slug should not be None for {c[0]}"
            assert ' ' not in c[1], f"Slug should not contain spaces for {c[0]}"

        print("  ✓ Drill-down links: PASSED")
        return True

    except Exception as e:
        print(f"  ✗ Drill-down links: FAILED - {e}")
        return False
    finally:
        db.close()


def test_api_endpoint_response():
    """Test API endpoint response structure."""
    print("\n=== Test 7: API Response Structure ===")

    db = SessionLocal()
    try:
        # Get a company with SEO data
        company = db.query(Company).join(
            CompanyWebsiteAnalysis,
            Company.id == CompanyWebsiteAnalysis.company_id
        ).filter(
            CompanyWebsiteAnalysis.seo_audited_at != None
        ).first()

        if not company:
            print("  No company with SEO data found")
            return False

        # Get analysis
        analysis = db.query(CompanyWebsiteAnalysis).filter(
            CompanyWebsiteAnalysis.company_id == company.id
        ).first()

        # Build response structure (simulating API)
        response = {
            'company_id': company.id,
            'company_name': company.name,
            'website': company.website,
            'seo_audit': {
                'audited_at': analysis.seo_audited_at.isoformat() if analysis.seo_audited_at else None,
                'pagespeed': {
                    'seo_score': analysis.pagespeed_seo_score,
                    'performance_score': analysis.pagespeed_performance_score,
                    'accessibility_score': analysis.pagespeed_accessibility_score,
                    'best_practices_score': analysis.pagespeed_best_practices_score
                },
                'on_page': {
                    'meta_title': analysis.meta_title,
                    'meta_description': analysis.meta_description,
                    'h1_count': analysis.h1_count,
                    'h2_count': analysis.h2_count,
                    'images_without_alt': analysis.images_without_alt,
                    'has_structured_data': analysis.has_structured_data
                },
                'technical': {
                    'has_ssl': analysis.has_ssl,
                    'has_sitemap': analysis.has_sitemap,
                    'has_robots_txt': analysis.has_robots_txt,
                    'has_canonical': analysis.has_canonical,
                    'is_indexable': analysis.is_indexable
                }
            }
        }

        print(f"  Company: {response['company_name']}")
        print(f"  SEO Score: {response['seo_audit']['pagespeed']['seo_score']}")
        print(f"  Has all required fields: Yes")

        # Verify structure
        assert 'company_id' in response
        assert 'seo_audit' in response
        assert 'pagespeed' in response['seo_audit']
        assert 'on_page' in response['seo_audit']
        assert 'technical' in response['seo_audit']

        print("  ✓ API response structure: PASSED")
        return True

    except Exception as e:
        print(f"  ✗ API response structure: FAILED - {e}")
        return False
    finally:
        db.close()


def test_template_rendering_data():
    """Test that template has all required data."""
    print("\n=== Test 8: Template Data Requirements ===")

    db = SessionLocal()
    try:
        # Check that we have all the data the template needs
        companies_count = db.query(Company).filter(Company.status == 'active').count()
        seo_count = db.query(CompanyWebsiteAnalysis).filter(
            CompanyWebsiteAnalysis.seo_audited_at != None
        ).count()

        required_data = {
            'companies': companies_count > 0,
            'stats.good_count': True,
            'stats.medium_count': True,
            'stats.poor_count': True,
            'stats.not_audited_count': True,
            'stats.avg_score': True,
            'categories': True,  # Could be empty
            'now': True,
            'csrf_token': True  # Provided by Flask
        }

        print("  Template requirements:")
        for key, available in required_data.items():
            status = "✓" if available else "✗"
            print(f"    {status} {key}")

        print(f"\n  Total companies: {companies_count}")
        print(f"  With SEO data: {seo_count}")

        print("  ✓ Template data requirements: PASSED")
        return True

    except Exception as e:
        print(f"  ✗ Template data requirements: FAILED - {e}")
        return False
    finally:
        db.close()


def main():
    """Run all tests."""
    print("=" * 60)
    print("Admin SEO Dashboard Tests")
    print("=" * 60)

    tests = [
        test_dashboard_data_query,
        test_statistics_calculation,
        test_score_color_coding,
        test_sorting_logic,
        test_filtering_logic,
        test_drill_down_links,
        test_api_endpoint_response,
        test_template_rendering_data,
    ]

    results = []
    for test in tests:
        try:
            result = test()
            results.append((test.__name__, result))
        except Exception as e:
            print(f"\n✗ {test.__name__} crashed: {e}")
            results.append((test.__name__, False))

    print("\n" + "=" * 60)
    print("Test Summary")
    print("=" * 60)

    passed = sum(1 for _, r in results if r)
    failed = len(results) - passed

    for name, result in results:
        status = "PASSED" if result else "FAILED"
        print(f"  {name}: {status}")

    print(f"\nTotal: {passed}/{len(results)} tests passed")

    if failed > 0:
        print(f"\n⚠️  {failed} test(s) failed!")
        sys.exit(1)
    else:
        print("\n✓ All tests passed!")
        sys.exit(0)


if __name__ == '__main__':
    main()
