#!/usr/bin/env python3
"""
Genesis API Usage Reporter
==========================
Real-time reporting and visualization for API usage metrics.

Provides:
1. Real-time usage dashboards
2. Cost projections
3. Historical trend analysis
4. Budget alerts via Slack
5. Self-awareness reporting for autonomous agents
"""

import json
from datetime import datetime, timedelta, timezone
from dataclasses import dataclass
from typing import Dict, List, Optional, Any
from pathlib import Path


def utcnow() -> datetime:
    """Get current UTC time as timezone-aware datetime."""
    return datetime.now(timezone.utc)


from api_usage_tracker import (
    APIUsageTracker,
    get_tracker,
    TokenEstimator,
    CostCalculator,
    MODEL_PRICING
)


# ============================================================================
# SELF-AWARENESS REPORT
# ============================================================================

class AgentSelfAwareness:
    """
    Self-awareness module for autonomous agents.

    Enables agents to:
    1. Understand their own resource consumption
    2. Make cost-aware decisions
    3. Self-regulate based on budgets
    4. Report their efficiency metrics
    """

    def __init__(self, tracker: Optional[APIUsageTracker] = None):
        self.tracker = tracker or get_tracker()
        self.awareness_start = utcnow()

    def get_self_assessment(self) -> Dict[str, Any]:
        """
        Generate a self-assessment of API usage.

        Returns a dictionary that an agent can use to understand
        its own resource consumption and make informed decisions.
        """
        session_stats = self.tracker.get_session_stats()
        daily = self.tracker.get_daily_usage()
        weekly = self.tracker.get_weekly_usage()
        monthly = self.tracker.get_monthly_usage()

        # Budget awareness
        budget = self.tracker.budget
        daily_remaining = max(0, budget.daily_limit_usd - daily)
        weekly_remaining = max(0, budget.weekly_limit_usd - weekly)
        monthly_remaining = max(0, budget.monthly_limit_usd - monthly)

        # Efficiency metrics
        if "error" not in session_stats and session_stats["total_requests"] > 0:
            tokens_per_request = session_stats["total_tokens"] / session_stats["total_requests"]
            cost_per_request = session_stats["total_cost_usd"] / session_stats["total_requests"]
            output_ratio = session_stats["output_tokens"] / max(1, session_stats["input_tokens"])
        else:
            tokens_per_request = 0
            cost_per_request = 0
            output_ratio = 0

        return {
            "timestamp": utcnow().isoformat(),
            "model_in_use": "claude-opus-4-5-20251101",

            # Current session
            "session": {
                "active": "error" not in session_stats,
                "requests": session_stats.get("total_requests", 0),
                "tokens_used": session_stats.get("total_tokens", 0),
                "cost_usd": session_stats.get("total_cost_usd", 0)
            },

            # Budget status
            "budget": {
                "daily_used_usd": round(daily, 4),
                "daily_remaining_usd": round(daily_remaining, 4),
                "daily_percent_used": round(daily / budget.daily_limit_usd * 100, 1),
                "weekly_used_usd": round(weekly, 4),
                "weekly_remaining_usd": round(weekly_remaining, 4),
                "weekly_percent_used": round(weekly / budget.weekly_limit_usd * 100, 1),
                "monthly_used_usd": round(monthly, 4),
                "monthly_remaining_usd": round(monthly_remaining, 4),
                "monthly_percent_used": round(monthly / budget.monthly_limit_usd * 100, 1)
            },

            # Efficiency metrics
            "efficiency": {
                "avg_tokens_per_request": round(tokens_per_request, 1),
                "avg_cost_per_request_usd": round(cost_per_request, 6),
                "output_to_input_ratio": round(output_ratio, 2)
            },

            # Decision guidance
            "guidance": self._generate_guidance(
                daily, daily_remaining,
                cost_per_request, output_ratio
            )
        }

    def _generate_guidance(
        self,
        daily_used: float,
        daily_remaining: float,
        cost_per_request: float,
        output_ratio: float
    ) -> Dict[str, Any]:
        """Generate guidance for cost-aware decisions."""
        guidance = {
            "can_continue": daily_remaining > 0,
            "recommendations": []
        }

        # Budget recommendations
        if daily_remaining < 1.0:
            guidance["recommendations"].append(
                "LOW DAILY BUDGET: Consider deferring non-essential tasks"
            )

        if daily_remaining < 0.1:
            guidance["recommendations"].append(
                "CRITICAL: Daily budget nearly exhausted. Pause non-essential operations."
            )

        # Efficiency recommendations
        if output_ratio > 3.0:
            guidance["recommendations"].append(
                "HIGH OUTPUT RATIO: Responses are verbose. Consider more concise outputs."
            )

        if cost_per_request > 0.05:
            guidance["recommendations"].append(
                "HIGH COST/REQUEST: Consider batching operations or using smaller models for simple tasks."
            )

        if not guidance["recommendations"]:
            guidance["recommendations"].append("Operating within normal parameters.")

        # Estimate remaining requests at current rate
        if cost_per_request > 0:
            guidance["estimated_remaining_requests"] = int(daily_remaining / cost_per_request)
        else:
            guidance["estimated_remaining_requests"] = "unlimited"

        return guidance

    def format_self_awareness_report(self) -> str:
        """Format a human-readable self-awareness report."""
        assessment = self.get_self_assessment()

        lines = [
            "=" * 60,
            "GENESIS AGENT SELF-AWARENESS REPORT",
            f"Model: {assessment['model_in_use']}",
            f"Generated: {assessment['timestamp']}",
            "=" * 60,
            "",
            "I. CURRENT SESSION STATUS",
            "-" * 40,
        ]

        session = assessment["session"]
        if session["active"]:
            lines.extend([
                f"  Requests Made: {session['requests']}",
                f"  Tokens Used: {session['tokens_used']:,}",
                f"  Cost Incurred: ${session['cost_usd']:.4f}",
            ])
        else:
            lines.append("  No active session")

        lines.extend([
            "",
            "II. BUDGET AWARENESS",
            "-" * 40,
        ])

        budget = assessment["budget"]
        lines.extend([
            f"  Daily:   ${budget['daily_used_usd']:.4f} used, ${budget['daily_remaining_usd']:.4f} remaining ({budget['daily_percent_used']:.1f}%)",
            f"  Weekly:  ${budget['weekly_used_usd']:.4f} used, ${budget['weekly_remaining_usd']:.4f} remaining ({budget['weekly_percent_used']:.1f}%)",
            f"  Monthly: ${budget['monthly_used_usd']:.4f} used, ${budget['monthly_remaining_usd']:.4f} remaining ({budget['monthly_percent_used']:.1f}%)",
        ])

        lines.extend([
            "",
            "III. EFFICIENCY METRICS",
            "-" * 40,
        ])

        efficiency = assessment["efficiency"]
        lines.extend([
            f"  Avg Tokens/Request: {efficiency['avg_tokens_per_request']:.1f}",
            f"  Avg Cost/Request: ${efficiency['avg_cost_per_request_usd']:.6f}",
            f"  Output/Input Ratio: {efficiency['output_to_input_ratio']:.2f}",
        ])

        lines.extend([
            "",
            "IV. GUIDANCE & RECOMMENDATIONS",
            "-" * 40,
        ])

        guidance = assessment["guidance"]
        lines.append(f"  Can Continue: {'YES' if guidance['can_continue'] else 'NO - BUDGET EXHAUSTED'}")
        lines.append(f"  Est. Remaining Requests: {guidance['estimated_remaining_requests']}")
        lines.append("")
        lines.append("  Recommendations:")
        for rec in guidance["recommendations"]:
            lines.append(f"    - {rec}")

        lines.extend([
            "",
            "=" * 60,
        ])

        return "\n".join(lines)


# ============================================================================
# COST PROJECTION
# ============================================================================

class CostProjector:
    """Project future costs based on usage patterns."""

    def __init__(self, tracker: Optional[APIUsageTracker] = None):
        self.tracker = tracker or get_tracker()

    def project_daily_cost(self, hours_remaining: Optional[float] = None) -> Dict[str, float]:
        """Project daily cost based on current usage rate."""
        session_stats = self.tracker.get_session_stats()

        if "error" in session_stats or session_stats["total_requests"] == 0:
            return {"projected_cost_usd": 0, "confidence": "low"}

        # Calculate hourly rate
        duration_hours = session_stats["duration_minutes"] / 60
        if duration_hours < 0.1:
            return {"projected_cost_usd": 0, "confidence": "low"}

        hourly_rate = session_stats["total_cost_usd"] / duration_hours

        # Calculate hours remaining in day
        if hours_remaining is None:
            now = utcnow()
            hours_remaining = 24 - now.hour - (now.minute / 60)

        # Already spent today
        daily_spent = self.tracker.get_daily_usage()

        # Project
        projected_additional = hourly_rate * hours_remaining
        projected_total = daily_spent + projected_additional

        return {
            "current_daily_spend_usd": round(daily_spent, 4),
            "projected_additional_usd": round(projected_additional, 4),
            "projected_total_usd": round(projected_total, 4),
            "hourly_rate_usd": round(hourly_rate, 4),
            "hours_remaining": round(hours_remaining, 1),
            "confidence": "medium" if duration_hours > 0.5 else "low"
        }

    def project_monthly_cost(self) -> Dict[str, float]:
        """Project monthly cost based on current patterns."""
        history = self.tracker.get_historical_data(days=7)

        # Calculate average daily spend
        costs = [d["cost_usd"] for d in history if d["cost_usd"] > 0]

        if not costs:
            return {"projected_cost_usd": 0, "confidence": "low"}

        avg_daily = sum(costs) / len(costs)

        # Days remaining in month
        now = utcnow()
        days_in_month = 30  # Simplified
        days_remaining = days_in_month - now.day

        # Current monthly spend
        monthly_spent = self.tracker.get_monthly_usage()

        projected_additional = avg_daily * days_remaining
        projected_total = monthly_spent + projected_additional

        return {
            "current_monthly_spend_usd": round(monthly_spent, 4),
            "avg_daily_rate_usd": round(avg_daily, 4),
            "days_remaining": days_remaining,
            "projected_additional_usd": round(projected_additional, 4),
            "projected_total_usd": round(projected_total, 4),
            "confidence": "medium" if len(costs) >= 3 else "low"
        }


# ============================================================================
# HISTORICAL ANALYSIS
# ============================================================================

class UsageAnalyzer:
    """Analyze historical usage patterns."""

    def __init__(self, tracker: Optional[APIUsageTracker] = None):
        self.tracker = tracker or get_tracker()

    def get_trend_analysis(self, days: int = 7) -> Dict[str, Any]:
        """Analyze usage trends over time."""
        history = self.tracker.get_historical_data(days=days)

        if not history:
            return {"error": "No historical data"}

        costs = [d["cost_usd"] for d in history]
        requests = [d["requests"] for d in history]

        # Calculate trends
        if len(costs) >= 2:
            # Simple linear trend (positive = increasing)
            cost_trend = (costs[-1] - costs[0]) / len(costs)
            request_trend = (requests[-1] - requests[0]) / len(requests)
        else:
            cost_trend = 0
            request_trend = 0

        return {
            "period_days": days,
            "total_cost_usd": round(sum(costs), 4),
            "avg_daily_cost_usd": round(sum(costs) / len(costs), 4) if costs else 0,
            "max_daily_cost_usd": round(max(costs), 4) if costs else 0,
            "min_daily_cost_usd": round(min(costs), 4) if costs else 0,
            "total_requests": sum(requests),
            "avg_daily_requests": round(sum(requests) / len(requests), 1) if requests else 0,
            "cost_trend": "increasing" if cost_trend > 0 else "decreasing" if cost_trend < 0 else "stable",
            "request_trend": "increasing" if request_trend > 0 else "decreasing" if request_trend < 0 else "stable"
        }

    def identify_peak_usage(self, days: int = 30) -> List[Dict]:
        """Identify days with peak usage."""
        history = self.tracker.get_historical_data(days=days)

        # Sort by cost
        sorted_history = sorted(history, key=lambda x: x["cost_usd"], reverse=True)

        # Return top 5
        return sorted_history[:5]


# ============================================================================
# SLACK REPORTER
# ============================================================================

class SlackUsageReporter:
    """Report usage metrics to Slack."""

    def __init__(self, channel_id: str = "C0A5P5A119U"):
        self.channel_id = channel_id

    def format_daily_report(self, tracker: APIUsageTracker) -> str:
        """Format daily usage report for Slack."""
        daily = tracker.get_daily_usage()
        weekly = tracker.get_weekly_usage()
        monthly = tracker.get_monthly_usage()
        budget = tracker.budget

        return f"""*Genesis API Usage Report - Daily Summary*

*Today's Usage*
• Cost: ${daily:.4f} / ${budget.daily_limit_usd:.2f} ({daily/budget.daily_limit_usd*100:.1f}%)

*This Week*
• Cost: ${weekly:.4f} / ${budget.weekly_limit_usd:.2f} ({weekly/budget.weekly_limit_usd*100:.1f}%)

*This Month*
• Cost: ${monthly:.4f} / ${budget.monthly_limit_usd:.2f} ({monthly/budget.monthly_limit_usd*100:.1f}%)

_Generated: {utcnow().strftime('%Y-%m-%d %H:%M UTC')}_"""

    def format_alert(self, alert_type: str, message: str) -> str:
        """Format budget alert for Slack."""
        emoji = "⚠️" if "ALERT" in alert_type else "🚨"

        return f"""{emoji} *Genesis Budget Alert*

*Type:* {alert_type}
*Message:* {message}
*Time:* {utcnow().strftime('%Y-%m-%d %H:%M UTC')}

_Review usage at your earliest convenience._"""


# ============================================================================
# COMBINED REPORTER
# ============================================================================

class GenesisUsageReporter:
    """Combined usage reporting system."""

    def __init__(self):
        self.tracker = get_tracker()
        self.awareness = AgentSelfAwareness(self.tracker)
        self.projector = CostProjector(self.tracker)
        self.analyzer = UsageAnalyzer(self.tracker)

    def generate_comprehensive_report(self) -> str:
        """Generate comprehensive usage report."""
        lines = [
            "=" * 70,
            "GENESIS COMPREHENSIVE API USAGE REPORT",
            f"Generated: {utcnow().isoformat()}",
            "=" * 70,
        ]

        # Self-awareness section
        lines.append("\n" + self.awareness.format_self_awareness_report())

        # Projections
        lines.extend([
            "",
            "COST PROJECTIONS",
            "-" * 40,
        ])

        daily_proj = self.projector.project_daily_cost()
        monthly_proj = self.projector.project_monthly_cost()

        lines.extend([
            f"  Daily Projection: ${daily_proj.get('projected_total_usd', 0):.4f} (confidence: {daily_proj.get('confidence', 'low')})",
            f"  Monthly Projection: ${monthly_proj.get('projected_total_usd', 0):.4f} (confidence: {monthly_proj.get('confidence', 'low')})",
        ])

        # Trends
        lines.extend([
            "",
            "USAGE TRENDS (7 days)",
            "-" * 40,
        ])

        trends = self.analyzer.get_trend_analysis(7)
        if "error" not in trends:
            lines.extend([
                f"  Total Cost: ${trends['total_cost_usd']:.4f}",
                f"  Avg Daily: ${trends['avg_daily_cost_usd']:.4f}",
                f"  Cost Trend: {trends['cost_trend']}",
                f"  Request Trend: {trends['request_trend']}",
            ])
        else:
            lines.append("  No historical data available")

        lines.extend([
            "",
            "=" * 70,
        ])

        return "\n".join(lines)

    def get_quick_status(self) -> str:
        """Get quick status for inline reporting."""
        daily = self.tracker.get_daily_usage()
        budget = self.tracker.budget
        session = self.tracker.get_session_stats()

        status = f"[API: ${daily:.4f}/${budget.daily_limit_usd:.0f}]"

        if "error" not in session:
            status += f" [Session: {session['total_requests']} req, ${session['total_cost_usd']:.4f}]"

        return status


# ============================================================================
# TEST
# ============================================================================

def test_reporter():
    """Test the usage reporter."""
    print("=" * 60)
    print("TESTING USAGE REPORTER")
    print("=" * 60)

    reporter = GenesisUsageReporter()

    # Start a session and simulate some usage
    reporter.tracker.start_session()

    # Simulate requests
    for i in range(3):
        reporter.tracker.track_request(
            model="claude-opus-4-5-20251101",
            input_tokens=1000 + i * 500,
            output_tokens=500 + i * 200,
            operation=f"test_{i}"
        )

    # Print comprehensive report
    print(reporter.generate_comprehensive_report())

    # Print quick status
    print("\nQuick Status:", reporter.get_quick_status())

    # End session
    reporter.tracker.end_session()

    print("\n" + "=" * 60)
    print("REPORTER TEST COMPLETE")
    print("=" * 60)


if __name__ == "__main__":
    test_reporter()
