"""
Validation script: Verify DimensionResolverService is integrated correctly across all posting modules.

This script checks:
1. Dimensions are seeded and available
2. Dimension requirements are linked to GL accounts
3. Journal entries have dimension assignments
4. All posting modules apply dimensions correctly
"""

from app.core.database import SessionLocal
from app.models.accounting_dimensions import AccountingDimension, AccountingDimensionValue, AccountingDimensionAssignment
from app.models.accounting_code_dimensions import AccountingCodeDimensionRequirement
from app.models.accounting import JournalEntry, AccountingCode
from sqlalchemy import func

def validate():
    db = SessionLocal()
    try:
        print("=" * 70)
        print("DIMENSION RESOLVER INTEGRATION VALIDATION")
        print("=" * 70)

        # 1. Check dimensions exist
        dim_count = db.query(AccountingDimension).count()
        print(f"\n[OK] Dimensions seeded: {dim_count}")
        if dim_count == 0:
            print("  [ERROR] No dimensions found!")
            return False

        dims = db.query(AccountingDimension).all()
        for dim in dims:
            val_count = db.query(AccountingDimensionValue).filter(
                AccountingDimensionValue.dimension_id == dim.id
            ).count()
            print(f"  - {dim.code}: {dim.name} ({val_count} values)")

        # 2. Check dimension requirements are linked
        req_count = db.query(AccountingCodeDimensionRequirement).count()
        print(f"\n[OK] Dimension requirements linked: {req_count}")
        if req_count == 0:
            print("  [ERROR] No dimension requirements found!")
            return False

        # Group by account type
        req_by_type = {}
        for acct in db.query(AccountingCode).all():
            reqs = db.query(AccountingCodeDimensionRequirement).filter(
                AccountingCodeDimensionRequirement.accounting_code_id == acct.id
            ).count()
            if reqs > 0:
                acct_type = acct.account_type
                if acct_type not in req_by_type:
                    req_by_type[acct_type] = []
                req_by_type[acct_type].append((acct.code, reqs))

        for acct_type in sorted(req_by_type.keys()):
            examples = req_by_type[acct_type][:2]
            print(f"  - {acct_type}: {len(examples)} example accounts with requirements")
            for code, count in examples:
                print(f"    * {code}: {count} requirements")

        # 3. Check journal entries and assignments
        je_count = db.query(JournalEntry).count()
        da_count = db.query(AccountingDimensionAssignment).count()
        avg_dims = da_count / je_count if je_count > 0 else 0

        print(f"\n[OK] Journal entries created: {je_count}")
        print(f"[OK] Dimension assignments created: {da_count}")
        print(f"[OK] Average dimensions per entry: {avg_dims:.1f}")

        if je_count == 0:
            print("  [ERROR] No journal entries found!")
            return False

        if da_count == 0:
            print("  [ERROR] No dimension assignments found!")
            return False

        # 4. Check coverage - entries with dimensions vs without
        entries_with_dims = (
            db.query(JournalEntry.id)
            .join(AccountingDimensionAssignment,
                  AccountingDimensionAssignment.journal_entry_id == JournalEntry.id)
            .group_by(JournalEntry.id)
            .count()
        )
        coverage = (entries_with_dims / je_count * 100) if je_count > 0 else 0
        print(f"[OK] Entries with dimension assignments: {entries_with_dims}/{je_count} ({coverage:.1f}%)")

        if coverage < 90:
            print(f"  [WARN] Low coverage - only {coverage:.1f}% of entries have dimensions")

        # 5. Check distribution across dimension types
        print(f"\n[OK] Dimension assignment distribution:")
        dim_dist = (
            db.query(AccountingDimension.code, func.count(AccountingDimensionAssignment.id))
            .join(AccountingDimensionAssignment,
                  AccountingDimensionAssignment.dimension_id == AccountingDimension.id)
            .group_by(AccountingDimension.code)
            .order_by(func.count(AccountingDimensionAssignment.id).desc())
            .all()
        )
        for dim_code, count in dim_dist:
            print(f"  - {dim_code}: {count} assignments")

        # 6. Sample entries with full details
        print(f"\n[OK] Sample entries (first 3):")
        samples = db.query(JournalEntry).order_by(JournalEntry.created_at).limit(3).all()
        for entry in samples:
            acct = db.query(AccountingCode).filter(AccountingCode.id == entry.accounting_code_id).first()
            dims = db.query(AccountingDimensionAssignment).filter(
                AccountingDimensionAssignment.journal_entry_id == entry.id
            ).all()
            print(f"  - {entry.description} ({acct.code}) -> {len(dims)} dimensions")

        print(f"\n" + "=" * 70)
        print("[SUCCESS] ALL VALIDATION CHECKS PASSED")
        print("=" * 70)
        return True

    except Exception as e:
        print(f"\n[ERROR] VALIDATION ERROR: {e}")
