"""
M365 Copilot Usage Sync — Pulls per-user Copilot usage data from Microsoft Graph API.

Graph endpoint: GET /v1.0/copilot/reports/getMicrosoft365CopilotUsageUserDetail(period='D30')
Returns: per-user last activity dates across Copilot apps (Teams, Word, Excel, PPT, Outlook, Chat)

Creates/updates "tool_usage" ActivityCompletions with monthly period keys.
"""

import random
from datetime import datetime, timezone
from uuid import UUID

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.models.activity import Activity, ActivityCompletion
from app.models.sync import DataSourceConfig
from app.models.user import User
from app.services.sync.base import BaseSyncService, SyncResult


class CopilotSyncService(BaseSyncService):
    source_name = "m365_copilot"

    def __init__(self, graph_client=None):
        self.graph = graph_client

    async def _execute_sync(self, db: AsyncSession, config: DataSourceConfig) -> SyncResult:
        """Pull Copilot usage from Graph API and create monthly completions."""
        result = SyncResult()

        if not self.graph or not self.graph.is_configured:
            result.errors.append("Graph API not configured")
            return result

        # Fetch usage data
        data = await self.graph.get(
            "copilot/reports/getMicrosoft365CopilotUsageUserDetail(period='D30')",
            params={"$format": "application/json"},
        )

        users_data = data.get("value", [])
        period_key = datetime.now(timezone.utc).strftime("%Y-%m")

        # Find the Copilot tool_usage activity
        activity = await self._get_or_create_copilot_activity(db)

        for user_data in users_data:
            result.records_processed += 1
            email = user_data.get("userPrincipalName", "")
            last_activity = user_data.get("lastActivityDate", "")

            if not email or not last_activity:
                continue

            user = await self._match_user_by_email(db, email)
            if not user:
                result.records_failed += 1
                continue

            # Upsert completion for this month
            existing = await db.execute(
                select(ActivityCompletion).where(
                    ActivityCompletion.user_id == user.id,
                    ActivityCompletion.activity_id == activity.id,
                    ActivityCompletion.period_key == period_key,
                )
            )
            comp = existing.scalar_one_or_none()

            if comp:
                comp.status = "completed"
                comp.source_detail = f"graph_copilot_sync_{datetime.now(timezone.utc).strftime('%Y-%m-%d')}"
                result.records_updated += 1
            else:
                comp = ActivityCompletion(
                    user_id=user.id,
                    activity_id=activity.id,
                    status="completed",
                    progress_pct=100,
                    completed_at=datetime.now(timezone.utc),
                    source="api_sync",
                    source_detail=f"graph_copilot_sync_{datetime.now(timezone.utc).strftime('%Y-%m-%d')}",
                    trust_tier=1,
                    period_key=period_key,
                )
                db.add(comp)
                result.records_created += 1

        return result

    async def _generate_demo_data(self, db: AsyncSession, config: DataSourceConfig) -> SyncResult:
        """Generate realistic demo Copilot usage data."""
        result = SyncResult()
        period_key = datetime.now(timezone.utc).strftime("%Y-%m")

        activity = await self._get_or_create_copilot_activity(db)

        # Get all active users
        users_result = await db.execute(
            select(User).where(User.is_active == True)  # noqa: E712
        )
        all_users = users_result.scalars().all()

        # ~70% of users are active Copilot users in demo
        active_users = random.sample(all_users, k=int(len(all_users) * 0.7))

        for user in active_users:
            result.records_processed += 1

            existing = await db.execute(
                select(ActivityCompletion).where(
                    ActivityCompletion.user_id == user.id,
                    ActivityCompletion.activity_id == activity.id,
                    ActivityCompletion.period_key == period_key,
                )
            )
            if existing.scalar_one_or_none():
                result.records_updated += 1
                continue

            comp = ActivityCompletion(
                user_id=user.id,
                activity_id=activity.id,
                status="completed",
                progress_pct=100,
                completed_at=datetime.now(timezone.utc),
                source="api_sync",
                source_detail="demo_copilot_sync",
                trust_tier=1,
                period_key=period_key,
            )
            db.add(comp)
            result.records_created += 1

        return result

    async def _get_or_create_copilot_activity(self, db: AsyncSession) -> Activity:
        """Get or create the monthly Copilot usage activity."""
        result = await db.execute(
            select(Activity).where(
                Activity.platform == "m365_copilot",
                Activity.category == "tool_usage",
                Activity.is_recurring == True,  # noqa: E712
            )
        )
        activity = result.scalar_one_or_none()

        if not activity:
            activity = Activity(
                title="Microsoft 365 Copilot Active Usage",
                description="Monthly active usage of Copilot across M365 apps",
                category="tool_usage",
                platform="m365_copilot",
                xp_value=30,
                is_recurring=True,
                recurrence_period="monthly",
                trust_tier=1,
                is_active=True,
            )
            db.add(activity)
            await db.flush()

        return activity
