#!/usr/bin/env python3
"""
Google Ads Agency Agent - Core Module
Shared utilities, API client, and data structures.
"""

import sys
import os
import json
from datetime import datetime, timedelta
from pathlib import Path
from dataclasses import dataclass, asdict
from typing import Optional, List, Dict, Any
from enum import Enum

# Add google-ads library path
sys.path.insert(0, '/Users/dominiquezhoumacmini/Library/Python/3.9/lib/python/site-packages')

from google.ads.googleads.client import GoogleAdsClient

# Paths
SKILL_DIR = Path(__file__).parent.parent
DATA_DIR = SKILL_DIR / "data"
DATA_DIR.mkdir(exist_ok=True)

# Account configuration
ACCOUNTS = {
    "US_NEW": {
        "name": "Elde Ventures LLC - US",
        "id": "2949069258",
        "currency": "USD",
        "timezone": "America/New_York",
        "priority": 1,
    },
    "US_OLD": {
        "name": "ZEDE PARIS - US",
        "id": "7480586470", 
        "currency": "USD",
        "timezone": "America/New_York",
        "priority": 2,
    },
    "FR_EU": {
        "name": "Zede Paris FR/EU",
        "id": "7441745274",
        "currency": "EUR",
        "timezone": "Europe/Paris",
        "priority": 1,
    },
}

# Default thresholds (can be overridden in data/thresholds.json)
DEFAULT_THRESHOLDS = {
    "waste_threshold_usd": 50,
    "high_cpa_multiplier": 2.0,
    "budget_pacing_min": 0.7,
    "budget_pacing_max": 1.1,
    "cpc_spike_threshold": 0.3,
    "min_impressions_for_analysis": 100,
    "conversion_gap_hours": 4,
    "quality_score_min": 5,
}


class Severity(Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"


class ActionType(Enum):
    PAUSE_KEYWORD = "pause_keyword"
    ENABLE_KEYWORD = "enable_keyword"
    PAUSE_CAMPAIGN = "pause_campaign"
    ENABLE_CAMPAIGN = "enable_campaign"
    ADJUST_BUDGET = "adjust_budget"
    ADJUST_BID = "adjust_bid"
    ADD_NEGATIVE = "add_negative"
    ADD_KEYWORD = "add_keyword"


@dataclass
class Issue:
    """Represents a detected issue."""
    type: str
    severity: Severity
    account: str
    message: str
    details: Dict[str, Any]
    timestamp: datetime = None
    
    def __post_init__(self):
        if self.timestamp is None:
            self.timestamp = datetime.now()
    
    def to_dict(self):
        d = asdict(self)
        d['severity'] = self.severity.value
        d['timestamp'] = self.timestamp.isoformat()
        return d
    
    def format_telegram(self) -> str:
        """Format for Telegram message."""
        emoji = {
            Severity.LOW: "📝",
            Severity.MEDIUM: "⚠️",
            Severity.HIGH: "🔴",
            Severity.CRITICAL: "🚨",
        }
        return f"{emoji[self.severity]} **{self.type}** ({self.account})\n{self.message}"


@dataclass
class Recommendation:
    """Represents an optimization recommendation."""
    id: str
    action: ActionType
    account: str
    target: str  # campaign/keyword/ad group name
    target_id: str
    reason: str
    expected_impact: str
    confidence: float  # 0-1
    details: Dict[str, Any]
    created_at: datetime = None
    status: str = "pending"  # pending, approved, rejected, executed
    
    def __post_init__(self):
        if self.created_at is None:
            self.created_at = datetime.now()
    
    def to_dict(self):
        d = asdict(self)
        d['action'] = self.action.value
        d['created_at'] = self.created_at.isoformat()
        return d
    
    @classmethod
    def from_dict(cls, d):
        d['action'] = ActionType(d['action'])
        d['created_at'] = datetime.fromisoformat(d['created_at'])
        return cls(**d)


@dataclass
class ChangeLog:
    """Represents a change made to the account."""
    id: str
    action: ActionType
    account: str
    target: str
    target_id: str
    old_value: Any
    new_value: Any
    reason: str
    executed_at: datetime
    recommendation_id: Optional[str] = None
    
    def to_dict(self):
        d = asdict(self)
        d['action'] = self.action.value
        d['executed_at'] = self.executed_at.isoformat()
        return d


def get_client() -> GoogleAdsClient:
    """Get authenticated Google Ads API client."""
    return GoogleAdsClient.load_from_storage(
        os.path.expanduser("~/.google-ads.yaml")
    )


def get_thresholds() -> Dict[str, Any]:
    """Load thresholds, with defaults."""
    threshold_file = DATA_DIR / "thresholds.json"
    thresholds = DEFAULT_THRESHOLDS.copy()
    
    if threshold_file.exists():
        with open(threshold_file) as f:
            custom = json.load(f)
            thresholds.update(custom)
    
    return thresholds


def save_thresholds(thresholds: Dict[str, Any]):
    """Save custom thresholds."""
    threshold_file = DATA_DIR / "thresholds.json"
    with open(threshold_file, 'w') as f:
        json.dump(thresholds, f, indent=2)


def load_recommendations() -> List[Recommendation]:
    """Load pending recommendations."""
    rec_file = DATA_DIR / "recommendations.json"
    if not rec_file.exists():
        return []
    
    with open(rec_file) as f:
        data = json.load(f)
    
    return [Recommendation.from_dict(r) for r in data]


def save_recommendations(recs: List[Recommendation]):
    """Save recommendations."""
    rec_file = DATA_DIR / "recommendations.json"
    with open(rec_file, 'w') as f:
        json.dump([r.to_dict() for r in recs], f, indent=2)


def add_recommendation(rec: Recommendation):
    """Add a new recommendation."""
    recs = load_recommendations()
    recs.append(rec)
    save_recommendations(recs)


def load_change_log() -> List[Dict]:
    """Load change history."""
    log_file = DATA_DIR / "changes_log.json"
    if not log_file.exists():
        return []
    
    with open(log_file) as f:
        return json.load(f)


def log_change(change: ChangeLog):
    """Log a change to history."""
    log_file = DATA_DIR / "changes_log.json"
    changes = load_change_log()
    changes.append(change.to_dict())
    
    # Keep last 1000 changes
    changes = changes[-1000:]
    
    with open(log_file, 'w') as f:
        json.dump(changes, f, indent=2)


def micros_to_currency(micros: int) -> float:
    """Convert micros to currency value."""
    return micros / 1_000_000


def format_currency(value: float, currency: str = "USD") -> str:
    """Format currency for display."""
    symbol = {"USD": "$", "EUR": "€", "GBP": "£"}.get(currency, currency)
    return f"{symbol}{value:,.2f}"


def format_percent(value: float) -> str:
    """Format percentage for display."""
    return f"{value:+.1f}%"


def date_range_query(days: int = 7) -> str:
    """Generate GAQL date range for last N days."""
    if days == 7:
        return "LAST_7_DAYS"
    elif days == 30:
        return "LAST_30_DAYS"
    elif days == 1:
        return "TODAY"
    else:
        end = datetime.now().date()
        start = end - timedelta(days=days)
        return f"'{start}' AND '{end}'"


def yesterday_date() -> str:
    """Get yesterday's date in YYYY-MM-DD format."""
    return (datetime.now().date() - timedelta(days=1)).strftime('%Y-%m-%d')


def today_date() -> str:
    """Get today's date in YYYY-MM-DD format."""
    return datetime.now().date().strftime('%Y-%m-%d')


def run_query(client: GoogleAdsClient, customer_id: str, query: str) -> List[Any]:
    """Run a GAQL query and return results as list."""
    ga_service = client.get_service("GoogleAdsService")
    try:
        response = ga_service.search(customer_id=customer_id, query=query)
        return list(response)
    except Exception as e:
        print(f"Query error: {e}", file=sys.stderr)
        return []


# Telegram formatting helpers
def telegram_section(title: str, content: str) -> str:
    """Format a section for Telegram."""
    return f"**{title}**\n{content}\n"


def telegram_table(headers: List[str], rows: List[List[str]]) -> str:
    """Format a simple table for Telegram (using monospace)."""
    # Calculate column widths
    widths = [len(h) for h in headers]
    for row in rows:
        for i, cell in enumerate(row):
            widths[i] = max(widths[i], len(str(cell)))
    
    # Format header
    header = " | ".join(h.ljust(widths[i]) for i, h in enumerate(headers))
    separator = "-+-".join("-" * w for w in widths)
    
    # Format rows
    formatted_rows = []
    for row in rows:
        formatted_rows.append(" | ".join(str(c).ljust(widths[i]) for i, c in enumerate(row)))
    
    return f"```\n{header}\n{separator}\n" + "\n".join(formatted_rows) + "\n```"


if __name__ == "__main__":
    # Quick test
    print("Google Ads Agency Agent - Core Module")
    print(f"Data directory: {DATA_DIR}")
    print(f"Thresholds: {get_thresholds()}")
    print(f"Accounts: {list(ACCOUNTS.keys())}")
