#!/usr/bin/env python3
"""
Genesis Revenue Tracker Core
=============================
Tracks revenue from AIVA recommendations and system operations.

PM-038: Revenue Tracker Core
- Tracks: source, amount, attribution
- Calculates: daily, weekly, monthly totals
- Stores revenue events persistently
"""

import os
import json
import logging
from typing import Dict, Any, List, Optional
from datetime import datetime, timedelta
from pathlib import Path
from collections import defaultdict
from dataclasses import dataclass, asdict

logger = logging.getLogger("RevenueTracker")
logging.basicConfig(level=logging.INFO)


@dataclass
class RevenueEvent:
    """Represents a revenue event."""
    event_id: str
    source: str
    amount: float
    currency: str
    attribution_id: Optional[str]
    attribution_type: str  # direct, assisted, influenced
    metadata: Dict[str, Any]
    timestamp: str

    def to_dict(self) -> Dict[str, Any]:
        return asdict(self)


class RevenueTracker:
    """
    Core revenue tracking system for Genesis.
    Tracks revenue events and calculates aggregated metrics.
    """

    def __init__(self, storage_path: str = None, redis_client=None):
        """
        Initialize revenue tracker.

        Args:
            storage_path: Path for JSON storage (default: data/revenue)
            redis_client: Optional Redis client for real-time tracking
        """
        self.storage_path = Path(storage_path or "data/revenue")
        self.storage_path.mkdir(parents=True, exist_ok=True)
        self.redis = redis_client

        # In-memory cache
        self.events_cache: List[RevenueEvent] = []
        self.daily_totals: Dict[str, float] = defaultdict(float)

        # Load existing events
        self._load_events()

        logger.info(f"Revenue Tracker initialized (storage: {self.storage_path})")

    def _load_events(self) -> None:
        """Load events from persistent storage."""
        events_file = self.storage_path / "events.jsonl"
        if events_file.exists():
            try:
                with open(events_file, 'r') as f:
                    for line in f:
                        if line.strip():
                            data = json.loads(line)
                            event = RevenueEvent(**data)
                            self.events_cache.append(event)
                            date_key = event.timestamp[:10]
                            self.daily_totals[date_key] += event.amount

                logger.info(f"Loaded {len(self.events_cache)} revenue events")
            except Exception as e:
                logger.error(f"Failed to load events: {e}")

    def _save_event(self, event: RevenueEvent) -> None:
        """Persist event to storage."""
        events_file = self.storage_path / "events.jsonl"
        try:
            with open(events_file, 'a') as f:
                f.write(json.dumps(event.to_dict()) + "\n")
        except Exception as e:
            logger.error(f"Failed to save event: {e}")

    def _generate_event_id(self) -> str:
        """Generate unique event ID."""
        import uuid
        return f"rev_{uuid.uuid4().hex[:12]}"

    def log(self, source: str, amount: float, currency: str = "USD",
            attribution_id: str = None, attribution_type: str = "direct",
            metadata: Dict[str, Any] = None) -> RevenueEvent:
        """
        Log a revenue event.

        Args:
            source: Revenue source (e.g., "ghl_workflow", "tradie_funnel", "voice_ai")
            amount: Revenue amount
            currency: Currency code (default: USD)
            attribution_id: ID of AIVA action that generated this revenue
            attribution_type: Type of attribution (direct, assisted, influenced)
            metadata: Additional event metadata

        Returns:
            Created RevenueEvent
        """
        event = RevenueEvent(
            event_id=self._generate_event_id(),
            source=source,
            amount=amount,
            currency=currency,
            attribution_id=attribution_id,
            attribution_type=attribution_type,
            metadata=metadata or {},
            timestamp=datetime.utcnow().isoformat()
        )

        # Add to cache
        self.events_cache.append(event)

        # Update daily total
        date_key = event.timestamp[:10]
        self.daily_totals[date_key] += amount

        # Persist
        self._save_event(event)

        # Update Redis if available
        if self.redis:
            try:
                self.redis.zadd("genesis:revenue_events",
                               {json.dumps(event.to_dict()): datetime.utcnow().timestamp()})
                self.redis.incrbyfloat(f"genesis:revenue:daily:{date_key}", amount)
            except Exception as e:
                logger.error(f"Redis update failed: {e}")

        logger.info(f"Revenue logged: {source} ${amount:.2f} ({attribution_type})")
        return event

    def get_daily_total(self, date: str = None) -> float:
        """
        Get total revenue for a specific day.

        Args:
            date: Date string (YYYY-MM-DD). Default: today

        Returns:
            Total revenue for the day
        """
        date = date or datetime.utcnow().strftime("%Y-%m-%d")
        return self.daily_totals.get(date, 0.0)

    def get_weekly_total(self, week_start: str = None) -> float:
        """
        Get total revenue for a week.

        Args:
            week_start: Start date (YYYY-MM-DD). Default: current week

        Returns:
            Total revenue for the week
        """
        if week_start:
            start = datetime.strptime(week_start, "%Y-%m-%d")
        else:
            today = datetime.utcnow()
            start = today - timedelta(days=today.weekday())

        total = 0.0
        for i in range(7):
            date_key = (start + timedelta(days=i)).strftime("%Y-%m-%d")
            total += self.daily_totals.get(date_key, 0.0)

        return total

    def get_monthly_total(self, year_month: str = None) -> float:
        """
        Get total revenue for a month.

        Args:
            year_month: Month string (YYYY-MM). Default: current month

        Returns:
            Total revenue for the month
        """
        if year_month:
            prefix = year_month
        else:
            prefix = datetime.utcnow().strftime("%Y-%m")

        total = 0.0
        for date_key, amount in self.daily_totals.items():
            if date_key.startswith(prefix):
                total += amount

        return total

    def get_totals_summary(self) -> Dict[str, float]:
        """
        Get comprehensive totals summary.

        Returns:
            Dict with daily, weekly, monthly, and all-time totals
        """
        now = datetime.utcnow()
        today = now.strftime("%Y-%m-%d")
        week_start = (now - timedelta(days=now.weekday())).strftime("%Y-%m-%d")
        month = now.strftime("%Y-%m")

        all_time = sum(self.daily_totals.values())

        return {
            "daily": self.get_daily_total(today),
            "weekly": self.get_weekly_total(week_start),
            "monthly": self.get_monthly_total(month),
            "all_time": all_time,
            "currency": "USD",
            "as_of": now.isoformat()
        }

    def get_events_by_source(self, source: str,
                             limit: int = 100) -> List[Dict[str, Any]]:
        """Get revenue events by source."""
        events = [e for e in self.events_cache if e.source == source]
        return [e.to_dict() for e in events[-limit:]]

    def get_events_by_date_range(self, start_date: str,
                                  end_date: str) -> List[Dict[str, Any]]:
        """Get revenue events within a date range."""
        events = [
            e for e in self.events_cache
            if start_date <= e.timestamp[:10] <= end_date
        ]
        return [e.to_dict() for e in events]

    def get_source_breakdown(self, period: str = "monthly") -> Dict[str, float]:
        """
        Get revenue breakdown by source.

        Args:
            period: Time period (daily, weekly, monthly, all_time)

        Returns:
            Dict mapping source to total revenue
        """
        now = datetime.utcnow()

        if period == "daily":
            cutoff = now.strftime("%Y-%m-%d")
        elif period == "weekly":
            cutoff = (now - timedelta(days=now.weekday())).strftime("%Y-%m-%d")
        elif period == "monthly":
            cutoff = now.strftime("%Y-%m")
        else:
            cutoff = "2000-01-01"  # All time

        breakdown = defaultdict(float)
        for event in self.events_cache:
            if event.timestamp[:len(cutoff)] >= cutoff:
                breakdown[event.source] += event.amount

        return dict(breakdown)

    def get_attribution_breakdown(self, period: str = "monthly") -> Dict[str, float]:
        """
        Get revenue breakdown by attribution type.

        Args:
            period: Time period (daily, weekly, monthly, all_time)

        Returns:
            Dict mapping attribution type to total revenue
        """
        now = datetime.utcnow()

        if period == "monthly":
            cutoff = now.strftime("%Y-%m")
        else:
            cutoff = "2000-01-01"

        breakdown = defaultdict(float)
        for event in self.events_cache:
            if event.timestamp[:len(cutoff)] >= cutoff:
                breakdown[event.attribution_type] += event.amount

        return dict(breakdown)

    def get_recent_events(self, limit: int = 50) -> List[Dict[str, Any]]:
        """Get most recent revenue events."""
        return [e.to_dict() for e in self.events_cache[-limit:]]

    def get_metrics(self) -> Dict[str, Any]:
        """Get comprehensive revenue metrics."""
        totals = self.get_totals_summary()
        source_breakdown = self.get_source_breakdown()
        attribution_breakdown = self.get_attribution_breakdown()

        return {
            "totals": totals,
            "by_source": source_breakdown,
            "by_attribution": attribution_breakdown,
            "total_events": len(self.events_cache),
            "unique_sources": len(set(e.source for e in self.events_cache))
        }

    def export_to_json(self, filepath: str) -> bool:
        """Export all events to JSON file."""
        try:
            with open(filepath, 'w') as f:
                json.dump({
                    "events": [e.to_dict() for e in self.events_cache],
                    "totals": self.get_totals_summary(),
                    "exported_at": datetime.utcnow().isoformat()
                }, f, indent=2)
            return True
        except Exception as e:
            logger.error(f"Export failed: {e}")
            return False


# Global instance for easy access
_tracker: Optional[RevenueTracker] = None


def get_tracker() -> RevenueTracker:
    """Get or create global revenue tracker instance."""
    global _tracker
    if _tracker is None:
        _tracker = RevenueTracker()
    return _tracker


if __name__ == "__main__":
    # Self-test
    tracker = RevenueTracker(storage_path="/tmp/genesis_revenue_test")

    # Log test events
    tracker.log(
        source="ghl_workflow",
        amount=500.00,
        attribution_id="aiva_task_123",
        attribution_type="direct",
        metadata={"client": "Test Tradie", "service": "Voice AI Setup"}
    )

    tracker.log(
        source="tradie_funnel",
        amount=250.00,
        attribution_id="aiva_task_456",
        attribution_type="assisted",
        metadata={"lead_source": "Google Ads"}
    )

    tracker.log(
        source="voice_ai_monthly",
        amount=199.00,
        attribution_type="influenced",
        metadata={"subscription": "premium"}
    )

    # Display metrics
    print("\n=== Revenue Tracker Test ===")
    print(f"Daily Total: ${tracker.get_daily_total():.2f}")
    print(f"Weekly Total: ${tracker.get_weekly_total():.2f}")
    print(f"Monthly Total: ${tracker.get_monthly_total():.2f}")
    print(f"\nSource Breakdown: {tracker.get_source_breakdown()}")
    print(f"\nAttribution Breakdown: {tracker.get_attribution_breakdown()}")
    print(f"\nFull Metrics: {json.dumps(tracker.get_metrics(), indent=2)}")
