#!/usr/bin/env python3
"""
Google Ads Agency Agent - Weekly Report Generator
Comprehensive weekly performance analysis.
"""

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

from core import (
    get_client, ACCOUNTS, run_query,
    micros_to_currency, format_currency, format_percent,
)


def get_period_metrics(client, customer_id: str, period: str) -> Dict[str, Any]:
    """Get aggregate metrics for a period."""
    query = f"""
        SELECT
            metrics.cost_micros,
            metrics.conversions,
            metrics.clicks,
            metrics.impressions,
            metrics.conversions_value
        FROM customer
        WHERE segments.date DURING {period}
    """
    
    results = run_query(client, customer_id, query)
    
    if not results:
        return None
    
    row = results[0]
    cost = micros_to_currency(row.metrics.cost_micros)
    conv = row.metrics.conversions
    clicks = row.metrics.clicks
    impressions = row.metrics.impressions
    
    return {
        'cost': cost,
        'conversions': conv,
        'clicks': clicks,
        'impressions': impressions,
        'cpa': cost / conv if conv > 0 else 0,
        'cpc': cost / clicks if clicks > 0 else 0,
        'ctr': (clicks / impressions * 100) if impressions > 0 else 0,
        'conv_rate': (conv / clicks * 100) if clicks > 0 else 0,
    }


def get_campaign_performance(client, customer_id: str, period: str) -> List[Dict]:
    """Get per-campaign performance."""
    query = f"""
        SELECT
            campaign.name,
            campaign.id,
            campaign.status,
            metrics.cost_micros,
            metrics.conversions,
            metrics.clicks,
            metrics.impressions
        FROM campaign
        WHERE segments.date DURING {period}
          AND metrics.cost_micros > 0
        ORDER BY metrics.cost_micros DESC
    """
    
    results = run_query(client, customer_id, query)
    
    campaigns = []
    for row in results:
        cost = micros_to_currency(row.metrics.cost_micros)
        conv = row.metrics.conversions
        
        campaigns.append({
            'name': row.campaign.name,
            'id': row.campaign.id,
            'status': row.campaign.status.name,
            'cost': cost,
            'conversions': conv,
            'clicks': row.metrics.clicks,
            'impressions': row.metrics.impressions,
            'cpa': cost / conv if conv > 0 else 0,
            'conv_rate': (conv / row.metrics.clicks * 100) if row.metrics.clicks > 0 else 0,
        })
    
    return campaigns


def get_top_keywords(client, customer_id: str, period: str, limit: int = 10) -> List[Dict]:
    """Get top performing keywords by conversions."""
    query = f"""
        SELECT
            ad_group_criterion.keyword.text,
            campaign.name,
            metrics.cost_micros,
            metrics.conversions,
            metrics.clicks
        FROM keyword_view
        WHERE segments.date DURING {period}
          AND metrics.conversions > 0
        ORDER BY metrics.conversions DESC
        LIMIT {limit}
    """
    
    results = run_query(client, customer_id, query)
    
    keywords = []
    for row in results:
        cost = micros_to_currency(row.metrics.cost_micros)
        conv = row.metrics.conversions
        
        keywords.append({
            'keyword': row.ad_group_criterion.keyword.text,
            'campaign': row.campaign.name,
            'cost': cost,
            'conversions': conv,
            'cpa': cost / conv if conv > 0 else 0,
        })
    
    return keywords


def get_worst_keywords(client, customer_id: str, period: str, limit: int = 10) -> List[Dict]:
    """Get worst performing keywords (high spend, low/no conversions)."""
    query = f"""
        SELECT
            ad_group_criterion.keyword.text,
            campaign.name,
            metrics.cost_micros,
            metrics.conversions,
            metrics.clicks
        FROM keyword_view
        WHERE segments.date DURING {period}
          AND metrics.cost_micros > 0
          AND metrics.conversions < 1
        ORDER BY metrics.cost_micros DESC
        LIMIT {limit}
    """
    
    results = run_query(client, customer_id, query)
    
    keywords = []
    for row in results:
        cost = micros_to_currency(row.metrics.cost_micros)
        
        keywords.append({
            'keyword': row.ad_group_criterion.keyword.text,
            'campaign': row.campaign.name,
            'cost': cost,
            'conversions': row.metrics.conversions,
            'clicks': row.metrics.clicks,
        })
    
    return keywords


def calculate_wow_change(current: float, previous: float) -> str:
    """Calculate week-over-week change."""
    if previous == 0:
        return "N/A"
    
    change = ((current - previous) / previous) * 100
    
    if change > 0:
        return f"↑ {change:.1f}%"
    elif change < 0:
        return f"↓ {abs(change):.1f}%"
    else:
        return "→ 0%"


def generate_weekly_report() -> str:
    """Generate comprehensive weekly report."""
    client = get_client()
    
    report = "📊 **Google Ads Weekly Report**\n"
    report += f"_Week ending {datetime.now().strftime('%B %d, %Y')}_\n\n"
    
    # Overall totals
    total_this_week = {'cost': 0, 'conversions': 0, 'clicks': 0}
    total_last_week = {'cost': 0, 'conversions': 0, 'clicks': 0}
    
    for account_key in ACCOUNTS:
        account = ACCOUNTS[account_key]
        
        report += f"━━━━━━━━━━━━━━━━━━━━\n"
        report += f"**{account['name']}**\n\n"
        
        # Get this week and last week metrics
        this_week = get_period_metrics(client, account['id'], "LAST_7_DAYS")
        
        # For last week comparison, we need custom date range
        end_date = datetime.now().date() - timedelta(days=7)
        start_date = end_date - timedelta(days=7)
        last_week_period = f"'{start_date}' AND '{end_date}'"
        last_week = get_period_metrics(client, account['id'], last_week_period)
        
        if not this_week:
            report += "_No data available_\n\n"
            continue
        
        # Add to totals
        total_this_week['cost'] += this_week['cost']
        total_this_week['conversions'] += this_week['conversions']
        total_this_week['clicks'] += this_week['clicks']
        
        if last_week:
            total_last_week['cost'] += last_week['cost']
            total_last_week['conversions'] += last_week['conversions']
            total_last_week['clicks'] += last_week['clicks']
        
        # Performance summary
        report += "**This Week:**\n"
        report += f"• Spend: {format_currency(this_week['cost'])} "
        if last_week:
            report += f"({calculate_wow_change(this_week['cost'], last_week['cost'])})\n"
        else:
            report += "\n"
        
        report += f"• Conversions: {this_week['conversions']:.0f} "
        if last_week:
            report += f"({calculate_wow_change(this_week['conversions'], last_week['conversions'])})\n"
        else:
            report += "\n"
        
        report += f"• CPA: {format_currency(this_week['cpa'])} "
        if last_week and last_week['cpa'] > 0:
            report += f"({calculate_wow_change(this_week['cpa'], last_week['cpa'])})\n"
        else:
            report += "\n"
        
        report += f"• Conv Rate: {this_week['conv_rate']:.2f}%\n"
        report += f"• CTR: {this_week['ctr']:.2f}%\n\n"
        
        # Top campaigns
        campaigns = get_campaign_performance(client, account['id'], "LAST_7_DAYS")
        
        if campaigns:
            report += "**Top Campaigns:**\n"
            for camp in campaigns[:3]:
                cpa_str = format_currency(camp['cpa']) if camp['cpa'] > 0 else "∞"
                report += f"• {camp['name'][:30]}: {format_currency(camp['cost'])} | {camp['conversions']:.0f} conv | CPA: {cpa_str}\n"
            report += "\n"
        
        # Top keywords
        top_kw = get_top_keywords(client, account['id'], "LAST_7_DAYS", 5)
        if top_kw:
            report += "**Top Keywords:**\n"
            for kw in top_kw[:3]:
                report += f"• '{kw['keyword'][:25]}': {kw['conversions']:.0f} conv @ {format_currency(kw['cpa'])} CPA\n"
            report += "\n"
        
        # Waste alert
        worst_kw = get_worst_keywords(client, account['id'], "LAST_7_DAYS", 5)
        wasted = sum(kw['cost'] for kw in worst_kw if kw['conversions'] == 0)
        if wasted > 50:
            report += f"⚠️ **Potential Waste:** {format_currency(wasted)} on zero-conversion keywords\n"
            report += "_Run 'find waste' for details_\n\n"
    
    # Grand totals
    report += "━━━━━━━━━━━━━━━━━━━━\n"
    report += "**TOTALS (All Accounts)**\n\n"
    
    total_cpa = total_this_week['cost'] / total_this_week['conversions'] if total_this_week['conversions'] > 0 else 0
    prev_cpa = total_last_week['cost'] / total_last_week['conversions'] if total_last_week['conversions'] > 0 else 0
    
    report += f"**This Week:**\n"
    report += f"• Total Spend: {format_currency(total_this_week['cost'])} "
    if total_last_week['cost'] > 0:
        report += f"({calculate_wow_change(total_this_week['cost'], total_last_week['cost'])})\n"
    else:
        report += "\n"
    
    report += f"• Total Conversions: {total_this_week['conversions']:.0f} "
    if total_last_week['conversions'] > 0:
        report += f"({calculate_wow_change(total_this_week['conversions'], total_last_week['conversions'])})\n"
    else:
        report += "\n"
    
    report += f"• Average CPA: {format_currency(total_cpa)} "
    if prev_cpa > 0:
        report += f"({calculate_wow_change(total_cpa, prev_cpa)})\n"
    else:
        report += "\n"
    
    # Weekly insights
    report += "\n**💡 Key Insights:**\n"
    
    if total_this_week['conversions'] > total_last_week['conversions'] * 1.1:
        report += "• 📈 Conversions up significantly - great week!\n"
    elif total_this_week['conversions'] < total_last_week['conversions'] * 0.9:
        report += "• 📉 Conversions down - review campaign changes\n"
    
    if total_cpa < prev_cpa * 0.9:
        report += "• 💰 CPA improved - efficiency gains working\n"
    elif total_cpa > prev_cpa * 1.2:
        report += "• ⚠️ CPA increased 20%+ - investigate causes\n"
    
    report += "\n_Use 'show pending recommendations' for optimization actions_"
    
    return report


def main():
    parser = argparse.ArgumentParser(description="Generate weekly Google Ads report")
    parser.add_argument("--json", action="store_true", help="Output as JSON")
    args = parser.parse_args()
    
    if args.json:
        # Would need to restructure for JSON output
        print("JSON output not yet implemented")
        sys.exit(1)
    else:
        print(generate_weekly_report())


if __name__ == "__main__":
    main()
