#!/usr/bin/env python3
"""
Google Ads Agency Agent - Change Tracker
Monitor the impact of changes we've made.
"""

import sys
import argparse
from datetime import datetime, timedelta
from typing import Dict, List, Any
import json

from core import (
    get_client, ACCOUNTS, run_query, load_change_log,
    micros_to_currency, format_currency, DATA_DIR,
    ActionType,
)


def get_keyword_performance_since(client, customer_id: str, keyword_id: str, ad_group_id: str, since_date: str) -> Dict:
    """Get keyword performance since a specific date."""
    query = f"""
        SELECT
            ad_group_criterion.keyword.text,
            metrics.cost_micros,
            metrics.conversions,
            metrics.clicks,
            metrics.impressions
        FROM keyword_view
        WHERE ad_group_criterion.criterion_id = {keyword_id}
          AND segments.date >= '{since_date}'
    """
    
    results = run_query(client, customer_id, query)
    
    if not results:
        return None
    
    total_cost = sum(micros_to_currency(r.metrics.cost_micros) for r in results)
    total_conv = sum(r.metrics.conversions for r in results)
    total_clicks = sum(r.metrics.clicks for r in results)
    
    return {
        'keyword': results[0].ad_group_criterion.keyword.text if results else 'unknown',
        'cost': total_cost,
        'conversions': total_conv,
        'clicks': total_clicks,
        'cpa': total_cost / total_conv if total_conv > 0 else 0,
    }


def get_campaign_performance_comparison(client, customer_id: str, campaign_id: str, change_date: str) -> Dict:
    """Compare campaign performance before and after a change."""
    # Days since change
    change_dt = datetime.fromisoformat(change_date.replace('Z', '+00:00').split('+')[0])
    days_since = (datetime.now() - change_dt).days
    
    if days_since < 1:
        return {"message": "Too soon to measure impact"}
    
    # Limit comparison period
    days_to_compare = min(days_since, 14)
    
    # Period after change
    after_start = change_dt.date()
    after_end = after_start + timedelta(days=days_to_compare)
    
    # Period before change (same duration)
    before_end = after_start - timedelta(days=1)
    before_start = before_end - timedelta(days=days_to_compare)
    
    query_after = f"""
        SELECT
            metrics.cost_micros,
            metrics.conversions,
            metrics.clicks
        FROM campaign
        WHERE campaign.id = {campaign_id}
          AND segments.date BETWEEN '{after_start}' AND '{after_end}'
    """
    
    query_before = f"""
        SELECT
            metrics.cost_micros,
            metrics.conversions,
            metrics.clicks
        FROM campaign
        WHERE campaign.id = {campaign_id}
          AND segments.date BETWEEN '{before_start}' AND '{before_end}'
    """
    
    after_results = run_query(client, customer_id, query_after)
    before_results = run_query(client, customer_id, query_before)
    
    def aggregate(results):
        cost = sum(micros_to_currency(r.metrics.cost_micros) for r in results)
        conv = sum(r.metrics.conversions for r in results)
        clicks = sum(r.metrics.clicks for r in results)
        return {
            'cost': cost,
            'conversions': conv,
            'clicks': clicks,
            'cpa': cost / conv if conv > 0 else 0,
        }
    
    before = aggregate(before_results)
    after = aggregate(after_results)
    
    return {
        'before': before,
        'after': after,
        'days_compared': days_to_compare,
        'cost_change': after['cost'] - before['cost'],
        'conversion_change': after['conversions'] - before['conversions'],
        'cpa_change': after['cpa'] - before['cpa'] if before['cpa'] > 0 else 0,
    }


def evaluate_change_impact(change: Dict) -> Dict:
    """Evaluate the impact of a single change."""
    client = get_client()
    
    # Find account ID
    account_id = None
    for key, acc in ACCOUNTS.items():
        if acc['name'] == change['account']:
            account_id = acc['id']
            break
    
    if not account_id:
        return {"error": f"Account not found: {change['account']}"}
    
    action = change['action']
    executed_at = change['executed_at']
    
    result = {
        'change_id': change['id'],
        'action': action,
        'target': change['target'],
        'executed_at': executed_at,
    }
    
    if action == ActionType.PAUSE_KEYWORD.value:
        # For paused keywords, we want to see how much we saved
        # The keyword is paused so we check spend before pause
        change_dt = datetime.fromisoformat(executed_at.replace('Z', '+00:00').split('+')[0])
        days_since = (datetime.now() - change_dt).days
        
        # Estimate savings based on pre-pause performance
        details = change.get('details', {}) or {}
        pre_pause_cost = details.get('current_cost', 0)
        
        if days_since > 0 and pre_pause_cost > 0:
            # Estimate daily burn rate
            daily_rate = pre_pause_cost / 7  # Assuming 7-day data
            estimated_savings = daily_rate * days_since
            
            result['status'] = 'positive'
            result['summary'] = f"Estimated savings: {format_currency(estimated_savings)}"
            result['estimated_savings'] = estimated_savings
        else:
            result['status'] = 'pending'
            result['summary'] = "Too early to measure"
    
    elif action == ActionType.ADD_NEGATIVE.value:
        # Check if the search term spend has stopped
        result['status'] = 'positive'
        result['summary'] = "Negative keyword active - blocking irrelevant searches"
    
    elif action == ActionType.ADJUST_BUDGET.value:
        # Compare campaign performance before/after
        details = change.get('details', {}) or {}
        campaign_id = details.get('campaign_id')
        
        if campaign_id:
            comparison = get_campaign_performance_comparison(client, account_id, campaign_id, executed_at)
            result['comparison'] = comparison
            
            if 'cost_change' in comparison:
                if comparison['conversion_change'] > 0:
                    result['status'] = 'positive'
                    result['summary'] = f"+{comparison['conversion_change']:.0f} conversions after budget change"
                elif comparison['cpa_change'] < 0:
                    result['status'] = 'positive'
                    result['summary'] = f"CPA improved by {format_currency(abs(comparison['cpa_change']))}"
                else:
                    result['status'] = 'neutral'
                    result['summary'] = "No significant change detected"
    
    return result


def track_all_changes(days: int = 7) -> List[Dict]:
    """Track impact of all recent changes."""
    changes = load_change_log()
    
    # Filter to recent changes
    cutoff = datetime.now() - timedelta(days=days)
    recent = [c for c in changes if datetime.fromisoformat(c['executed_at'].replace('Z', '+00:00').split('+')[0]) > cutoff]
    
    results = []
    for change in recent:
        try:
            impact = evaluate_change_impact(change)
            results.append(impact)
        except Exception as e:
            results.append({
                'change_id': change.get('id', 'unknown'),
                'error': str(e),
            })
    
    return results


def format_change_impact_report(results: List[Dict]) -> str:
    """Format change impact report for display."""
    if not results:
        return "📊 **Change Impact Report**\n\nNo recent changes to track."
    
    report = "📊 **Change Impact Report**\n\n"
    
    positive = [r for r in results if r.get('status') == 'positive']
    neutral = [r for r in results if r.get('status') == 'neutral']
    pending = [r for r in results if r.get('status') == 'pending']
    
    if positive:
        report += "✅ **Positive Impact**\n"
        for r in positive:
            report += f"• {r['action']}: {r['summary']}\n"
        report += "\n"
    
    if neutral:
        report += "➖ **Neutral**\n"
        for r in neutral:
            report += f"• {r['action']}: {r['summary']}\n"
        report += "\n"
    
    if pending:
        report += "⏳ **Pending Evaluation**\n"
        for r in pending:
            report += f"• {r['action']}: {r.get('summary', 'Collecting data...')}\n"
    
    total_savings = sum(r.get('estimated_savings', 0) for r in results)
    if total_savings > 0:
        report += f"\n💰 **Total Estimated Savings:** {format_currency(total_savings)}"
    
    return report


def save_impact_data(results: List[Dict]):
    """Save impact data for learning."""
    impact_file = DATA_DIR / "change_impacts.json"
    
    existing = []
    if impact_file.exists():
        with open(impact_file) as f:
            existing = json.load(f)
    
    # Update or add new results
    existing_ids = {r['change_id'] for r in existing}
    for result in results:
        if result['change_id'] not in existing_ids:
            result['tracked_at'] = datetime.now().isoformat()
            existing.append(result)
        else:
            # Update existing
            for i, ex in enumerate(existing):
                if ex['change_id'] == result['change_id']:
                    result['tracked_at'] = datetime.now().isoformat()
                    existing[i] = result
                    break
    
    # Keep last 500
    existing = existing[-500:]
    
    with open(impact_file, 'w') as f:
        json.dump(existing, f, indent=2)


def main():
    parser = argparse.ArgumentParser(description="Track Google Ads change impacts")
    parser.add_argument("--days", type=int, default=7, help="Track changes from last N days")
    parser.add_argument("--json", action="store_true", help="Output as JSON")
    args = parser.parse_args()
    
    results = track_all_changes(args.days)
    
    # Save for learning
    save_impact_data(results)
    
    if args.json:
        print(json.dumps(results, indent=2, default=str))
    else:
        print(format_change_impact_report(results))


if __name__ == "__main__":
    main()
