import aiohttp
from datetime import datetime, timedelta
from . import BaseAdPlatform


class YouTubeAdsPlatform(BaseAdPlatform):
    """Google Ads API integration for YouTube video campaigns."""

    BASE_URL = "https://googleads.googleapis.com/v17"

    def _headers(self, account):
        return {
            "Authorization": f"Bearer {account.access_token}",
            "developer-token": account.notes or "",  # Developer token stored in notes
            "Content-Type": "application/json",
        }

    async def upload_video(self, video_url: str, account) -> str:
        """YouTube videos must already be uploaded. Returns video URL as-is."""
        return video_url

    async def create_campaign(self, ad_campaign, account) -> dict:
        """Create YouTube video campaign via Google Ads API."""
        headers = self._headers(account)
        customer_id = account.account_id.replace("-", "")
        targeting = ad_campaign.targeting_json or {}

        async with aiohttp.ClientSession() as session:
            # 1. Create Campaign
            camp_url = f"{self.BASE_URL}/customers/{customer_id}/campaigns:mutate"
            start_date = ad_campaign.start_date or datetime.utcnow()
            end_date = ad_campaign.end_date or (start_date + timedelta(days=ad_campaign.duration_days or 7))

            camp_payload = {
                "operations": [{
                    "create": {
                        "name": ad_campaign.name,
                        "advertisingChannelType": "VIDEO",
                        "status": "PAUSED",
                        "campaignBudget": f"customers/{customer_id}/campaignBudgets/-1",
                        "startDate": start_date.strftime("%Y-%m-%d"),
                        "endDate": end_date.strftime("%Y-%m-%d"),
                    }
                }]
            }
            async with session.post(camp_url, json=camp_payload, headers=headers) as resp:
                result = await resp.json()
                if "results" not in result:
                    return {"status": "error", "error": f"Campaign creation failed: {result}"}
                campaign_resource = result["results"][0]["resourceName"]

            # 2. Create Budget
            budget_url = f"{self.BASE_URL}/customers/{customer_id}/campaignBudgets:mutate"
            budget_payload = {
                "operations": [{
                    "create": {
                        "name": f"{ad_campaign.name} Budget",
                        "amountMicros": str(int(ad_campaign.daily_budget * 1_000_000)),
                        "deliveryMethod": "STANDARD",
                    }
                }]
            }
            async with session.post(budget_url, json=budget_payload, headers=headers) as resp:
                budget_result = await resp.json()
                budget_resource = budget_result.get("results", [{}])[0].get("resourceName", "")

            # 3. Create Ad Group
            adgroup_url = f"{self.BASE_URL}/customers/{customer_id}/adGroups:mutate"
            adgroup_payload = {
                "operations": [{
                    "create": {
                        "name": f"{ad_campaign.name} - Ad Group",
                        "campaign": campaign_resource,
                        "type": "VIDEO_TRUE_VIEW_IN_STREAM",
                        "status": "ENABLED",
                        "cpcBidMicros": "100000",
                    }
                }]
            }
            async with session.post(adgroup_url, json=adgroup_payload, headers=headers) as resp:
                adgroup_result = await resp.json()
                adgroup_resource = adgroup_result.get("results", [{}])[0].get("resourceName", "")

            return {
                "status": "active",
                "campaign_id": campaign_resource,
                "budget_id": budget_resource,
                "adgroup_id": adgroup_resource,
            }

    async def get_metrics(self, platform_campaign_id: str, account, date_from=None, date_to=None) -> list:
        """Fetch metrics via Google Ads Query Language."""
        customer_id = account.account_id.replace("-", "")
        url = f"{self.BASE_URL}/customers/{customer_id}/googleAds:searchStream"
        if not date_from:
            date_from = (datetime.utcnow() - timedelta(days=7)).strftime("%Y-%m-%d")
        if not date_to:
            date_to = datetime.utcnow().strftime("%Y-%m-%d")

        query = f"""
            SELECT campaign.id, segments.date,
                   metrics.impressions, metrics.clicks, metrics.ctr,
                   metrics.cost_micros, metrics.video_views,
                   metrics.engagements, metrics.interactions
            FROM campaign
            WHERE campaign.resource_name = '{platform_campaign_id}'
            AND segments.date BETWEEN '{date_from}' AND '{date_to}'
        """
        metrics_list = []
        async with aiohttp.ClientSession() as session:
            async with session.post(url, json={"query": query}, headers=self._headers(account)) as resp:
                data = await resp.json()
                for batch in data if isinstance(data, list) else [data]:
                    for row in batch.get("results", []):
                        m = row.get("metrics", {})
                        seg = row.get("segments", {})
                        views = int(m.get("videoViews", 0))
                        clicks = int(m.get("clicks", 0))
                        spend = int(m.get("costMicros", 0)) / 1_000_000
                        metrics_list.append({
                            "date": seg.get("date", ""),
                            "impressions": int(m.get("impressions", 0)),
                            "views": views,
                            "clicks": clicks,
                            "ctr": float(m.get("ctr", 0)),
                            "spend": spend,
                            "cost_per_view": round(spend / views, 4) if views > 0 else 0,
                            "cost_per_click": round(spend / clicks, 4) if clicks > 0 else 0,
                            "likes": 0,
                            "comments": 0,
                            "shares": 0,
                            "reach": 0,
                            "frequency": 0,
                        })
        return metrics_list

    async def pause_campaign(self, platform_campaign_id: str, account) -> dict:
        customer_id = account.account_id.replace("-", "")
        url = f"{self.BASE_URL}/customers/{customer_id}/campaigns:mutate"
        payload = {"operations": [{"update": {"resourceName": platform_campaign_id, "status": "PAUSED"}, "updateMask": "status"}]}
        async with aiohttp.ClientSession() as session:
            async with session.post(url, json=payload, headers=self._headers(account)) as resp:
                return {"status": "paused"}

    async def resume_campaign(self, platform_campaign_id: str, account) -> dict:
        customer_id = account.account_id.replace("-", "")
        url = f"{self.BASE_URL}/customers/{customer_id}/campaigns:mutate"
        payload = {"operations": [{"update": {"resourceName": platform_campaign_id, "status": "ENABLED"}, "updateMask": "status"}]}
        async with aiohttp.ClientSession() as session:
            async with session.post(url, json=payload, headers=self._headers(account)) as resp:
                return {"status": "active"}

    async def delete_campaign(self, platform_campaign_id: str, account) -> dict:
        customer_id = account.account_id.replace("-", "")
        url = f"{self.BASE_URL}/customers/{customer_id}/campaigns:mutate"
        payload = {"operations": [{"remove": platform_campaign_id}]}
        async with aiohttp.ClientSession() as session:
            async with session.post(url, json=payload, headers=self._headers(account)) as resp:
                return {"status": "deleted"}
