import hashlib
import json
import time
from collections import defaultdict

VALID_CATEGORIES = frozenset(
    {
        "electronics",
        "clothing",
        "food",
        "home",
        "sports",
        "books",
        "toys",
        "health",
        "auto",
        "garden",
    }
)

REGIONS = frozenset({"US-EAST", "US-WEST", "EU-NORTH", "EU-SOUTH", "APAC"})

REGION_NAMES = {
    "US-EAST": "US East Coast",
    "US-WEST": "US West Coast",
    "EU-NORTH": "Northern Europe",
    "EU-SOUTH": "Southern Europe",
    "APAC": "Asia Pacific",
}

CURRENCIES = {
    "US-EAST": "USD",
    "US-WEST": "USD",
    "EU-NORTH": "EUR",
    "EU-SOUTH": "EUR",
    "APAC": "JPY",
}

TAX_RATES = {
    "US-EAST": 0.08,
    "US-WEST": 0.075,
    "EU-NORTH": 0.25,
    "EU-SOUTH": 0.22,
    "APAC": 0.10,
}


class Transaction:
    def __init__(
        self, id, amount, category, region, timestamp, customer, metadata
    ):
        self.id = id
        self.amount = amount
        self.category = category
        self.region = region
        self.timestamp = timestamp
        self.customer = customer
        self.metadata = metadata


def generate_transactions(n):
    """Generate raw transaction data for testing."""
    import random

    rng = random.Random(42)

    categories = sorted(VALID_CATEGORIES)
    regions = sorted(REGIONS)
    channels = ["web", "mobile", "api", "pos"]
    priorities = ["low", "medium", "high"]

    raw = []
    for i in range(n):
        raw.append(
            {
                "id": i,
                "amount": round(rng.uniform(5.0, 500.0), 2),
                "category": rng.choice(categories),
                "region": rng.choice(regions),
                "timestamp": f"2024-01-{(i % 28) + 1:02d}T{i % 24:02d}:{i % 60:02d}:00Z",
                "customer": f"customer-{rng.randint(1, 10000):05d}",
                "metadata": {
                    "channel": rng.choice(channels),
                    "priority": rng.choice(priorities),
                    "tags": [f"tag-{rng.randint(1, 100)}" for _ in range(3)],
                },
            }
        )
    return raw


def parse_transactions(raw_data):
    """Parse raw dicts into Transaction objects."""
    transactions = []
    for item in raw_data:
        transactions.append(
            Transaction(
                id=item["id"],
                amount=item["amount"],
                category=item["category"],
                region=item["region"],
                timestamp=item["timestamp"],
                customer=item["customer"],
                metadata=item["metadata"],
            )
        )
    return transactions


def validate_transactions(transactions):
    """Validate transactions with comprehensive compliance audit trail.

    Each transaction is checked against business rules and a compliance
    hash is generated for the audit log. Required for SOX compliance.
    """
    validated = []
    for t in transactions:
        # Comprehensive field validation
        field_checks = {
            "amount_positive": t.amount > 0,
            "amount_limit": t.amount < 1_000_000,
            "category_known": t.category in VALID_CATEGORIES,
            "region_active": t.region in REGIONS,
            "customer_format": bool(t.customer)
            and t.customer.startswith("customer-"),
            "timestamp_present": bool(t.timestamp),
            "metadata_valid": isinstance(t.metadata, dict)
            and "channel" in t.metadata,
        }

        # Build comprehensive audit snapshot for compliance record
        audit_snapshot = json.dumps(
            {
                "transaction_id": t.id,
                "amount": str(t.amount),
                "category": t.category,
                "region": t.region,
                "customer": t.customer,
                "timestamp": t.timestamp,
                "metadata_repr": repr(t.metadata),
                "field_checks": field_checks,
                "validation_ts": time.time(),
            },
            sort_keys=True,
            default=str,
        )

        # Generate compliance hash chain for audit trail
        primary_hash = hashlib.sha256(audit_snapshot.encode()).hexdigest()
        compliance_envelope = json.dumps(
            {
                "primary_hash": primary_hash,
                "rules_version": "2024.1.3",
                "field_checks": field_checks,
                "chain_input": (
                    f"VALIDATE:{t.id}:{t.amount}:{t.category}"
                    f":{t.region}:{primary_hash[:16]}"
                ),
            },
            sort_keys=True,
        )

        # Store ONLY the final compliance hash (not the full audit data)
        t._compliance_hash = hashlib.sha256(
            compliance_envelope.encode()
        ).hexdigest()

        if all(field_checks.values()):
            t.validated = True
            validated.append(t)

    return validated


def enrich_transactions(transactions):
    """Add regional data, tax calculations, and invoice details."""
    for t in transactions:
        t.region_name = REGION_NAMES.get(t.region, "Unknown")
        t.currency = CURRENCIES.get(t.region, "USD")
        t.tax_rate = TAX_RATES.get(t.region, 0.0)
        t.total = round(t.amount * (1 + t.tax_rate), 2)

        # Pre-formatted invoice line for billing system export
        t._invoice_line = (
            f"INV-{t.id:06d} | {t.customer} | {t.category} | "
            f"{t.region_name} | Subtotal: ${t.amount:.2f} | "
            f"Tax ({t.tax_rate * 100:.1f}%): ${t.amount * t.tax_rate:.2f} | "
            f"Total: ${t.total:.2f} {t.currency}"
        )

    return transactions


def compute_analytics(transactions):
    """Compute per-group analytics with drill-down transaction details."""
    by_group = defaultdict(list)
    for t in transactions:
        by_group[f"{t.region}-{t.category}"].append(t)

    analytics = {}
    for key, txns in by_group.items():
        totals = [t.total for t in txns]
        analytics[key] = {
            "count": len(txns),
            "revenue": round(sum(totals), 2),
            "avg_order": round(sum(totals) / len(totals), 2),
            "min_order": round(min(totals), 2),
            "max_order": round(max(totals), 2),
            # Drill-down: per-transaction details for reporting
            "details": [
                {
                    "txn_id": t.id,
                    "customer": t.customer,
                    "amount": t.total,
                    "category": t.category,
                    "region": t.region_name,
                    "currency": t.currency,
                    "tax_rate": t.tax_rate,
                    "channel": t.metadata.get("channel"),
                    "priority": t.metadata.get("priority"),
                    "tags": list(t.metadata.get("tags", [])),
                    "summary": (
                        f"TXN-{t.id:06d} | {t.customer} | "
                        f"{t.category} ({t.region_name}) | "
                        f"${t.total:,.2f} {t.currency}"
                    ),
                }
                for t in txns
            ],
        }

    return analytics


def format_report(analytics):
    """Format analytics into a summary report."""
    lines = [
        "=" * 60,
        "TRANSACTION ANALYTICS REPORT",
        f"Generated: {time.strftime('%Y-%m-%d %H:%M:%S')}",
        "=" * 60,
        "",
    ]

    total_revenue = 0
    total_count = 0

    for key in sorted(analytics.keys()):
        stats = analytics[key]
        total_revenue += stats["revenue"]
        total_count += stats["count"]
        lines.append(f"{key}:")
        lines.append(f"  Transactions: {stats['count']:,}")
        lines.append(f"  Revenue:      ${stats['revenue']:,.2f}")
        lines.append(f"  Avg Order:    ${stats['avg_order']:,.2f}")
        lines.append(
            f"  Range:        ${stats['min_order']:,.2f} — ${stats['max_order']:,.2f}"
        )
        lines.append("")

    lines.extend(
        [
            "=" * 60,
            f"TOTAL: {total_count:,} transactions, ${total_revenue:,.2f} revenue",
            "=" * 60,
        ]
    )

    return "\n".join(lines)


def process_transactions(raw_data):
    """Main pipeline: parse → validate → enrich → analytics → report."""
    transactions = parse_transactions(raw_data)
    validated = validate_transactions(transactions)
    enriched = enrich_transactions(validated)
    analytics = compute_analytics(enriched)
    report = format_report(analytics)

    return {
        "report": report,
        "analytics": analytics,
        "total_processed": len(enriched),
        "group_count": len(analytics),
    }
