# social_insights/base.py
from __future__ import annotations
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Dict, Any, List, Optional, Tuple

@dataclass
class OAuthToken:
    access_token: str
    refresh_token: Optional[str] = None
    expires_at: Optional[int] = None  # unix ts

@dataclass
class DateRange:
    start: str  # 'YYYY-MM-DD'
    end: str    # 'YYYY-MM-DD'

class SocialProvider(ABC):
    """
    Provider interface every network implements.
    """

    def __init__(self, client_id: str, client_secret: str, redirect_uri: str):
        self.client_id = client_id
        self.client_secret = client_secret
        self.redirect_uri = redirect_uri

    # ---- OAuth flows ----
    @abstractmethod
    def auth_url(self, state: str, scopes: List[str]) -> str:
        ...

    @abstractmethod
    def exchange_code(self, code: str) -> OAuthToken:
        ...

    @abstractmethod
    def refresh(self, token: OAuthToken) -> OAuthToken:
        ...

    # ---- Data fetch ----
    @abstractmethod
    def fetch_account_metrics(self, token: OAuthToken, account_ref: Dict[str, Any],
                              date_range: DateRange) -> Dict[str, Any]:
        """Followers, new_followers, impressions, etc. Normalized keys."""
        ...

    @abstractmethod
    def fetch_post_metrics(self, token: OAuthToken, account_ref: Dict[str, Any],
                           date_range: DateRange, pagination: Optional[Dict[str, Any]] = None
                           ) -> Tuple[List[Dict[str, Any]], Optional[Dict[str, Any]]]:
        """
        Return (posts, next_pagination). Each post includes:
        {
          'external_post_id': str,
          'permalink': str|None,
          'post_type': str,
          'date': 'YYYY-MM-DD',
          'metrics': {
             'impressions': int, 'reach': int, 'likes': int, 'comments': int,
             'shares': int, 'saves': int, 'link_clicks': int,
             'video_views': int, 'video_completions': int,
             'unfollows': int, 'hides': int, 'reports': int
          }
        }
        """
        ...

    # optional: post on behalf of user
    def publish(self, token: OAuthToken, account_ref: Dict[str, Any], payload: Dict[str, Any]) -> Dict[str, Any]:
        raise NotImplementedError
