#!/usr/bin/env python3
"""
Test script to verify purchase audit trail implementation.

This script:
1. Verifies model columns exist
2. Tests purchase creation with audit trail
3. Tests purchase approval with audit trail
4. Tests purchase posting with audit trail
5. Verifies API responses include audit fields
"""

import json
import sys
from datetime import datetime
from decimal import Decimal

# Import models and database
from app.models.purchases import Purchase
from app.models.user import User
from app.models.branch import Branch
from app.models.suppliers import Supplier
from app.core.database import SessionLocal, engine
from sqlalchemy import inspect


def check_model_columns():
    """Verify audit trail columns exist on Purchase model."""
    print("\n" + "=" * 80)
    print("CHECKING PURCHASE MODEL COLUMNS")
    print("=" * 80)

    inspector = inspect(engine)
    columns = {col['name']: col['type'] for col in inspector.get_columns('purchases')}

    required_cols = {
        'created_at': 'DateTime',
        'created_from_branch_id': 'String',
        'approved_at': 'DateTime',  # Changed from Date
        'approved_from_branch_id': 'String',
        'posted_from_branch_id': 'String',
    }

    all_exist = True
    for col_name, col_type in required_cols.items():
        exists = col_name in columns
        status = "✓" if exists else "✗"
        print(f"  {status} {col_name:30s} {str(columns.get(col_name, 'MISSING')):20s}")
        if not exists:
            all_exist = False

    return all_exist


def test_purchase_creation():
    """Test that purchase creation captures audit trail."""
    print("\n" + "=" * 80)
    print("TESTING PURCHASE CREATION AUDIT TRAIL")
    print("=" * 80)

    db = SessionLocal()
    try:
        # Get test data
        supplier = db.query(Supplier).first()
        branch = db.query(Branch).first()
        user = db.query(User).first()

        if not (supplier and branch and user):
            print("  ✗ Test data not available (supplier/branch/user)")
            return False

        print(f"  Using supplier: {supplier.name}")
        print(f"  Using branch: {branch.name}")
        print(f"  Using user: {user.username}")

        # Create a test purchase
        test_purchase = Purchase(
            supplier_id=supplier.id,
            purchase_date=datetime.utcnow().date(),
            total_amount=Decimal('1000.00'),
            branch_id=branch.id,
            created_by=user.id,
            created_at=datetime.utcnow(),
            created_from_branch_id=branch.id,
            status='pending'
        )

        db.add(test_purchase)
        db.commit()
        db.refresh(test_purchase)

        # Verify fields
        print(f"\n  ✓ Created purchase: {test_purchase.id}")
        print(f"    - created_by: {test_purchase.created_by}")
        print(f"    - created_at: {test_purchase.created_at}")
        print(f"    - created_from_branch_id: {test_purchase.created_from_branch_id}")

        return True

    except Exception as e:
        print(f"  ✗ Error: {e}")
        import traceback
        traceback.print_exc()
        return False
    finally:
        db.close()


def test_purchase_approval():
    """Test that purchase approval captures audit trail."""
    print("\n" + "=" * 80)
    print("TESTING PURCHASE APPROVAL AUDIT TRAIL")
    print("=" * 80)

    db = SessionLocal()
    try:
        # Get a pending purchase
        purchase = db.query(Purchase).filter(
            Purchase.status == 'pending',
            Purchase.approved_by.is_(None)
        ).first()

        if not purchase:
            print("  ⚠ No pending purchase available for approval test")
            return None

        user = db.query(User).first()

        # Simulate approval
        from datetime import datetime
        purchase.approved_by = user.id
        purchase.approved_at = datetime.utcnow()
        purchase.approved_from_branch_id = purchase.branch_id
        purchase.status = 'approved'

        db.commit()
        db.refresh(purchase)

        print(f"  ✓ Approved purchase: {purchase.id}")
        print(f"    - approved_by: {purchase.approved_by}")
        print(f"    - approved_at: {purchase.approved_at}")
        print(f"    - approved_from_branch_id: {purchase.approved_from_branch_id}")

        return True

    except Exception as e:
        print(f"  ✗ Error: {e}")
        import traceback
        traceback.print_exc()
        return False
    finally:
        db.close()


def test_purchase_posting():
    """Test that purchase posting captures audit trail."""
    print("\n" + "=" * 80)
    print("TESTING PURCHASE POSTING AUDIT TRAIL")
    print("=" * 80)

    db = SessionLocal()
    try:
        # Get an approved purchase
        purchase = db.query(Purchase).filter(
            Purchase.approved_by.isnot(None),
            Purchase.posted_by.is_(None)
        ).first()

        if not purchase:
            print("  ⚠ No approved purchase available for posting test")
            return None

        user = db.query(User).first()

        # Simulate posting
        from datetime import datetime
        purchase.posted_by = user.id
        purchase.last_posted_date = datetime.utcnow()
        purchase.posted_from_branch_id = purchase.branch_id
        purchase.posting_status = 'posted'

        db.commit()
        db.refresh(purchase)

        print(f"  ✓ Posted purchase: {purchase.id}")
        print(f"    - posted_by: {purchase.posted_by}")
        print(f"    - last_posted_date: {purchase.last_posted_date}")
        print(f"    - posted_from_branch_id: {purchase.posted_from_branch_id}")

        return True

    except Exception as e:
        print(f"  ✗ Error: {e}")
        import traceback
        traceback.print_exc()
        return False
    finally:
        db.close()


def test_response_schema():
    """Verify PurchaseResponse schema includes audit fields."""
    print("\n" + "=" * 80)
    print("CHECKING PURCHASE RESPONSE SCHEMA")
    print("=" * 80)

    from app.schemas.purchases import PurchaseResponse

    required_fields = [
        'created_by', 'created_by_name', 'created_at', 'created_from_branch_id',
        'approved_by', 'approved_by_name', 'approved_at', 'approved_from_branch_id',
        'posted_by', 'posted_by_name', 'last_posted_date', 'posted_from_branch_id',
    ]

    model_fields = set(PurchaseResponse.model_fields.keys())

    all_present = True
    for field in required_fields:
        present = field in model_fields
        status = "✓" if present else "✗"
        print(f"  {status} {field}")
        if not present:
            all_present = False

    return all_present


def main():
    """Run all tests."""
    print("\n" + "╔" + "=" * 78 + "╗")
    print("║" + " " * 78 + "║")
    print("║" + "PURCHASE AUDIT TRAIL VERIFICATION TEST".center(78) + "║")
    print("║" + " " * 78 + "║")
    print("╚" + "=" * 78 + "╝")

    results = {
        "Model Columns": check_model_columns(),
        "Response Schema": test_response_schema(),
        "Purchase Creation": test_purchase_creation(),
        "Purchase Approval": test_purchase_approval(),
        "Purchase Posting": test_purchase_posting(),
    }

    print("\n" + "=" * 80)
    print("TEST SUMMARY")
    print("=" * 80)

    for test_name, result in results.items():
        if result is True:
            status = "✓ PASSED"
        elif result is False:
            status = "✗ FAILED"
        else:
            status = "⊘ SKIPPED"
        print(f"  {test_name:30s} {status}")

    all_passed = all(v is not False for v in results.values())

    print()
    if all_passed:
        print("✓ ALL TESTS PASSED - Audit trail implementation is working correctly!")
    else:
        print("✗ SOME TESTS FAILED - Check the output above for details.")
        sys.exit(1)

    print()
    print("NEXT STEPS:")
    print("  1. Start the FastAPI server: python -m uvicorn app.main:app --reload")
    print("  2. Create a purchase via POST /api/v1/purchases/")
    print("  3. View purchase via GET /api/v1/purchases/by-id/{purchase_id}")
    print("  4. Verify all audit fields are present in the response")
    print()


if __name__ == "__main__":
    main()
