"""
Test script for Phase 2 Dimensional Code Generation Service.

Creates test templates and generates instances to verify functionality.
"""

import os
import sys
from datetime import datetime

# Ensure workspace root is on sys.path
WORKSPACE_ROOT = os.path.dirname(os.path.dirname(__file__))
if WORKSPACE_ROOT not in sys.path:
    sys.path.append(WORKSPACE_ROOT)

from sqlalchemy import text
from app.core.database import engine, SessionLocal
from app.models.accounting import AccountingCode, AccountingCodeInstance
from app.services.dimensional_code_service import DimensionalCodeService


def create_test_template():
    """Create a test dimensional template if it doesn't exist."""
    db = SessionLocal()

    try:
        # Check if test template already exists
        existing = db.query(AccountingCode).filter_by(code="4000-TEST").first()
        if existing:
            print(f"✓ Test template already exists: {existing.code} - {existing.name}")
            return existing

        # Create a test template
        template = AccountingCode(
            code="4000-TEST",
            name="Test Sales Revenue (Dimensional Template)",
            account_type="Revenue",
            category="Operating Revenue",
            is_parent=False,
            is_dimensional_template=True,
            dimension_pattern={
                "code_pattern": "4000-TEST-{branch}-{department}",
                "name_pattern": "Sales Revenue - {branch_name} - {department_name}",
                "required_dimensions": ["branch", "department"]
            },
            reporting_tag="IFRS_Revenue",
            currency="BWP"
        )

        db.add(template)
        db.commit()
        db.refresh(template)

        print(f"✓ Created test template: {template.code} - {template.name}")
        return template

    finally:
        db.close()


def test_pattern_parsing():
    """Test pattern parsing functionality."""
    print("\n=== Testing Pattern Parsing ===")

    db = SessionLocal()
    service = DimensionalCodeService(db)

    try:
        # Test basic pattern
        pattern = "4000-{branch}-{dept}"
        values = {
            "branch": "HQ",
            "dept": "IT"
        }
        result = service.parse_pattern(pattern, values)
        print(f"Pattern: {pattern}")
        print(f"Values: {values}")
        print(f"Result: {result}")
        assert result == "4000-HQ-IT", f"Expected '4000-HQ-IT', got '{result}'"
        print("✓ Basic pattern parsing works")

        # Test with _name suffix
        pattern = "Sales - {branch_name} - {dept_name}"
        values = {
            "branch_name": "Headquarters",
            "dept_name": "IT Department"
        }
        result = service.parse_pattern(pattern, values)
        print(f"\nPattern: {pattern}")
        print(f"Values: {values}")
        print(f"Result: {result}")
        assert result == "Sales - Headquarters - IT Department"
        print("✓ Pattern with _name suffix works")

        # Test with formatting
        pattern = "4000-{branch:upper}-{dept:5}"
        values = {
            "branch": "hq",
            "dept": "IT"
        }
        result = service.parse_pattern(pattern, values)
        print(f"\nPattern: {pattern}")
        print(f"Values: {values}")
        print(f"Result: {result}")
        assert result == "4000-HQ-IT000", f"Expected '4000-HQ-IT000', got '{result}'"
        print("✓ Pattern with formatting works")

    finally:
        db.close()


def test_instance_generation():
    """Test instance generation."""
    print("\n=== Testing Instance Generation ===")

    db = SessionLocal()
    service = DimensionalCodeService(db)

    try:
        # Get the test template
        template = db.query(AccountingCode).filter_by(code="4000-TEST").first()
        if not template:
            print("✗ Test template not found. Run create_test_template() first.")
            return

        # Validate template
        is_valid, error = service.validate_template(template)
        print(f"Template validation: {is_valid}")
        if not is_valid:
            print(f"Validation error: {error}")
            return
        print("✓ Template is valid")

        # Preview instance
        print("\nPreviewing instance...")
        dimension_values = {
            "branch": "HQ",
            "branch_code": "HQ",
            "branch_name": "Headquarters",
            "department": "IT",
            "department_code": "IT",
            "department_name": "IT Department"
        }

        preview = service.preview_instance(
            base_code_id=template.id,
            dimension_values=dimension_values
        )
        print(f"Preview:")
        print(f"  Code: {preview['instance_code']}")
        print(f"  Name: {preview['name']}")
        print(f"  Type: {preview['account_type']}")
        print("✓ Preview works")

        # Check if instance already exists
        existing = db.query(AccountingCodeInstance).filter_by(
            instance_code=preview['instance_code']
        ).first()

        if existing:
            print(f"\n⚠ Instance already exists: {existing.instance_code}")
            print(f"  Deleting existing instance for clean test...")
            db.delete(existing)
            db.commit()

        # Generate instance
        print("\nGenerating instance...")
        instance = service.generate_instance(
            base_code_id=template.id,
            dimension_values=dimension_values
        )

        print(f"✓ Generated instance:")
        print(f"  ID: {instance.id}")
        print(f"  Code: {instance.instance_code}")
        print(f"  Name: {instance.name}")
        print(f"  Type: {instance.account_type}")
        print(f"  Dimensions: {instance.dimension_values}")

        # Verify it was saved
        saved = db.query(AccountingCodeInstance).filter_by(
            id=instance.id
        ).first()
        assert saved is not None, "Instance not saved to database"
        print("✓ Instance saved to database")

        # Test duplicate prevention
        print("\nTesting duplicate prevention...")
        try:
            service.generate_instance(
                base_code_id=template.id,
                dimension_values=dimension_values
            )
            print("✗ Duplicate was not prevented!")
        except ValueError as e:
            if "already exists" in str(e):
                print(f"✓ Duplicate prevented: {e}")
            else:
                raise

    finally:
        db.close()


def test_batch_generation():
    """Test batch instance generation."""
    print("\n=== Testing Batch Generation ===")

    db = SessionLocal()
    service = DimensionalCodeService(db)

    try:
        template = db.query(AccountingCode).filter_by(code="4000-TEST").first()
        if not template:
            print("✗ Test template not found")
            return

        # Delete any existing test instances
        print("Clearing existing test instances...")
        db.query(AccountingCodeInstance).filter(
            AccountingCodeInstance.instance_code.like("4000-TEST-%")
        ).delete(synchronize_session=False)
        db.commit()

        # Generate batch
        dimension_value_sets = [
            {
                "branch": "HQ",
                "branch_code": "HQ",
                "branch_name": "Headquarters",
                "department": "IT",
                "department_code": "IT",
                "department_name": "IT Department"
            },
            {
                "branch": "HQ",
                "branch_code": "HQ",
                "branch_name": "Headquarters",
                "department": "SALES",
                "department_code": "SALES",
                "department_name": "Sales Department"
            },
            {
                "branch": "BR1",
                "branch_code": "BR1",
                "branch_name": "Branch 1",
                "department": "IT",
                "department_code": "IT",
                "department_name": "IT Department"
            }
        ]

        print(f"Generating {len(dimension_value_sets)} instances...")
        instances = service.generate_instances_batch(
            base_code_id=template.id,
            dimension_value_sets=dimension_value_sets
        )

        print(f"✓ Generated {len(instances)} instances:")
        for inst in instances:
            print(f"  - {inst.instance_code}: {inst.name}")

        assert len(instances) == len(dimension_value_sets), "Not all instances were created"
        print("✓ Batch generation successful")

    finally:
        db.close()


def test_get_instances():
    """Test retrieving instances."""
    print("\n=== Testing Instance Retrieval ===")

    db = SessionLocal()
    service = DimensionalCodeService(db)

    try:
        template = db.query(AccountingCode).filter_by(code="4000-TEST").first()
        if not template:
            print("✗ Test template not found")
            return

        # Get all instances
        instances = service.get_instances_for_base_code(template.id)
        print(f"Total instances for base code: {len(instances)}")

        if instances:
            print("Instances:")
            for inst in instances:
                print(f"  - {inst.instance_code}: {inst.name}")
            print("✓ Instance retrieval works")
        else:
            print("⚠ No instances found (run test_batch_generation first)")

    finally:
        db.close()


def run_all_tests():
    """Run all tests in sequence."""
    print("=" * 60)
    print("Phase 2 Dimensional Code Generation - Test Suite")
    print("=" * 60)

    try:
        create_test_template()
        test_pattern_parsing()
        test_instance_generation()
        test_batch_generation()
        test_get_instances()

        print("\n" + "=" * 60)
        print("✓ All tests completed successfully!")
        print("=" * 60)

    except Exception as e:
        print("\n" + "=" * 60)
        print(f"✗ Test failed: {e}")
        print("=" * 60)
        import traceback
        traceback.print_exc()


if __name__ == '__main__':
    run_all_tests()
