"""
WordPress OAuth2 Service
Handles WordPress.com OAuth2 authentication flow for simplified user connection.
"""

import os
import secrets
import sqlite3
import requests
from typing import Optional, Dict, Any, List
from datetime import datetime, timedelta
from loguru import logger
import json
import base64

class WordPressOAuthService:
    """Manages WordPress.com OAuth2 authentication flow."""
    
    def __init__(self, db_path: str = "alwrity.db"):
        self.db_path = db_path
        # WordPress.com OAuth2 credentials
        self.client_id = os.getenv('WORDPRESS_CLIENT_ID', '')
        self.client_secret = os.getenv('WORDPRESS_CLIENT_SECRET', '')
        self.redirect_uri = os.getenv('WORDPRESS_REDIRECT_URI', 'https://alwrity-ai.vercel.app/wp/callback')
        self.base_url = "https://public-api.wordpress.com"

        # Validate configuration
        if not self.client_id or not self.client_secret or self.client_id == 'your_wordpress_com_client_id_here':
            logger.error("WordPress OAuth client credentials not configured. Please set WORDPRESS_CLIENT_ID and WORDPRESS_CLIENT_SECRET environment variables with valid WordPress.com application credentials.")
            logger.error("To get credentials: 1. Go to https://developer.wordpress.com/apps/ 2. Create a new application 3. Set redirect URI to: https://your-domain.com/wp/callback")

        self._init_db()
    
    def _init_db(self):
        """Initialize database tables for OAuth tokens."""
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS wordpress_oauth_tokens (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    user_id TEXT NOT NULL,
                    access_token TEXT NOT NULL,
                    refresh_token TEXT,
                    token_type TEXT DEFAULT 'bearer',
                    expires_at TIMESTAMP,
                    scope TEXT,
                    blog_id TEXT,
                    blog_url TEXT,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    is_active BOOLEAN DEFAULT TRUE
                )
            ''')
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS wordpress_oauth_states (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    state TEXT NOT NULL UNIQUE,
                    user_id TEXT NOT NULL,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    expires_at TIMESTAMP DEFAULT (datetime('now', '+10 minutes'))
                )
            ''')
            conn.commit()
        logger.info("WordPress OAuth database initialized.")
    
    def generate_authorization_url(self, user_id: str, scope: str = "global") -> Dict[str, Any]:
        """Generate WordPress OAuth2 authorization URL."""
        try:
            # Check if credentials are properly configured
            if not self.client_id or not self.client_secret or self.client_id == 'your_wordpress_com_client_id_here':
                logger.error("WordPress OAuth client credentials not configured")
                return None

            # Generate secure state parameter
            state = secrets.token_urlsafe(32)

            # Store state in database for validation
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    INSERT INTO wordpress_oauth_states (state, user_id)
                    VALUES (?, ?)
                ''', (state, user_id))
                conn.commit()

            # Build authorization URL
            # For WordPress.com, use "global" scope for full access to enable posting
            params = [
                f"client_id={self.client_id}",
                f"redirect_uri={self.redirect_uri}",
                "response_type=code",
                f"state={state}",
                f"scope={scope}"  # WordPress.com requires "global" scope for full access
            ]

            auth_url = f"{self.base_url}/oauth2/authorize?{'&'.join(params)}"

            logger.info(f"Generated WordPress OAuth URL for user {user_id}")
            logger.info(f"WordPress OAuth redirect URI: {self.redirect_uri}")
            return {
                "auth_url": auth_url,
                "state": state
            }

        except Exception as e:
            logger.error(f"Error generating WordPress OAuth URL: {e}")
            return None
    
    def handle_oauth_callback(self, code: str, state: str) -> Optional[Dict[str, Any]]:
        """Handle OAuth callback and exchange code for access token."""
        try:
            logger.info(f"WordPress OAuth callback started - code: {code[:20]}..., state: {state[:20]}...")
            
            # Validate state parameter
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    SELECT user_id FROM wordpress_oauth_states 
                    WHERE state = ? AND expires_at > datetime('now')
                ''', (state,))
                result = cursor.fetchone()
                
                if not result:
                    logger.error(f"Invalid or expired state parameter: {state}")
                    return None
                
                user_id = result[0]
                logger.info(f"WordPress OAuth: State validated for user {user_id}")
                
                # Clean up used state
                cursor.execute('DELETE FROM wordpress_oauth_states WHERE state = ?', (state,))
                conn.commit()
            
            # Exchange authorization code for access token
            token_data = {
                'client_id': self.client_id,
                'client_secret': self.client_secret,
                'redirect_uri': self.redirect_uri,
                'code': code,
                'grant_type': 'authorization_code'
            }
            
            logger.info(f"WordPress OAuth: Exchanging code for token...")
            response = requests.post(
                f"{self.base_url}/oauth2/token",
                data=token_data,
                timeout=30
            )
            
            if response.status_code != 200:
                logger.error(f"Token exchange failed: {response.status_code} - {response.text}")
                return None
            
            token_info = response.json()
            logger.info(f"WordPress OAuth: Token received - blog_id: {token_info.get('blog_id')}, blog_url: {token_info.get('blog_url')}")
            
            # Store token information
            access_token = token_info.get('access_token')
            blog_id = token_info.get('blog_id')
            blog_url = token_info.get('blog_url')
            scope = token_info.get('scope', '')
            
            # Calculate expiration (WordPress tokens typically expire in 2 weeks)
            expires_at = datetime.now() + timedelta(days=14)
            
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    INSERT INTO wordpress_oauth_tokens 
                    (user_id, access_token, token_type, expires_at, scope, blog_id, blog_url)
                    VALUES (?, ?, ?, ?, ?, ?, ?)
                ''', (user_id, access_token, 'bearer', expires_at, scope, blog_id, blog_url))
                conn.commit()
                logger.info(f"WordPress OAuth: Token inserted into database for user {user_id}")
            
            logger.info(f"WordPress OAuth token stored successfully for user {user_id}, blog: {blog_url}")
            return {
                "success": True,
                "access_token": access_token,
                "blog_id": blog_id,
                "blog_url": blog_url,
                "scope": scope,
                "expires_at": expires_at.isoformat()
            }
            
        except Exception as e:
            logger.error(f"Error handling WordPress OAuth callback: {e}")
            return None
    
    def get_user_tokens(self, user_id: str) -> List[Dict[str, Any]]:
        """Get all active WordPress tokens for a user."""
        try:
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    SELECT id, access_token, token_type, expires_at, scope, blog_id, blog_url, created_at
                    FROM wordpress_oauth_tokens
                    WHERE user_id = ? AND is_active = TRUE AND expires_at > datetime('now')
                    ORDER BY created_at DESC
                ''', (user_id,))
                
                tokens = []
                for row in cursor.fetchall():
                    tokens.append({
                        "id": row[0],
                        "access_token": row[1],
                        "token_type": row[2],
                        "expires_at": row[3],
                        "scope": row[4],
                        "blog_id": row[5],
                        "blog_url": row[6],
                        "created_at": row[7]
                    })
                
                return tokens
                
        except Exception as e:
            logger.error(f"Error getting WordPress tokens for user {user_id}: {e}")
            return []
    
    def get_user_token_status(self, user_id: str) -> Dict[str, Any]:
        """Get detailed token status for a user including expired tokens."""
        try:
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                
                # Get all tokens (active and expired)
                cursor.execute('''
                    SELECT id, access_token, refresh_token, token_type, expires_at, scope, blog_id, blog_url, created_at, is_active
                    FROM wordpress_oauth_tokens
                    WHERE user_id = ?
                    ORDER BY created_at DESC
                ''', (user_id,))
                
                all_tokens = []
                active_tokens = []
                expired_tokens = []
                
                for row in cursor.fetchall():
                    token_data = {
                        "id": row[0],
                        "access_token": row[1],
                        "refresh_token": row[2],
                        "token_type": row[3],
                        "expires_at": row[4],
                        "scope": row[5],
                        "blog_id": row[6],
                        "blog_url": row[7],
                        "created_at": row[8],
                        "is_active": bool(row[9])
                    }
                    all_tokens.append(token_data)
                    
                    # Determine expiry using robust parsing and is_active flag
                    is_active_flag = bool(row[9])
                    not_expired = False
                    try:
                        expires_at_val = row[4]
                        if expires_at_val:
                            # First try Python parsing
                            try:
                                dt = datetime.fromisoformat(expires_at_val) if isinstance(expires_at_val, str) else expires_at_val
                                not_expired = dt > datetime.now()
                            except Exception:
                                # Fallback to SQLite comparison
                                cursor.execute("SELECT datetime('now') < ?", (expires_at_val,))
                                not_expired = cursor.fetchone()[0] == 1
                        else:
                            # No expiry stored => consider not expired
                            not_expired = True
                    except Exception:
                        not_expired = False

                    if is_active_flag and not_expired:
                        active_tokens.append(token_data)
                    else:
                        expired_tokens.append(token_data)
                
                return {
                    "has_tokens": len(all_tokens) > 0,
                    "has_active_tokens": len(active_tokens) > 0,
                    "has_expired_tokens": len(expired_tokens) > 0,
                    "active_tokens": active_tokens,
                    "expired_tokens": expired_tokens,
                    "total_tokens": len(all_tokens),
                    "last_token_date": all_tokens[0]["created_at"] if all_tokens else None
                }
                
        except Exception as e:
            logger.error(f"Error getting WordPress token status for user {user_id}: {e}")
            return {
                "has_tokens": False,
                "has_active_tokens": False,
                "has_expired_tokens": False,
                "active_tokens": [],
                "expired_tokens": [],
                "total_tokens": 0,
                "last_token_date": None,
                "error": str(e)
            }
    
    def test_token(self, access_token: str) -> bool:
        """Test if a WordPress access token is valid."""
        try:
            headers = {'Authorization': f'Bearer {access_token}'}
            response = requests.get(
                f"{self.base_url}/rest/v1/me/",
                headers=headers,
                timeout=10
            )
            
            return response.status_code == 200
            
        except Exception as e:
            logger.error(f"Error testing WordPress token: {e}")
            return False
    
    def revoke_token(self, user_id: str, token_id: int) -> bool:
        """Revoke a WordPress OAuth token."""
        try:
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    UPDATE wordpress_oauth_tokens 
                    SET is_active = FALSE, updated_at = datetime('now')
                    WHERE user_id = ? AND id = ?
                ''', (user_id, token_id))
                conn.commit()
                
                if cursor.rowcount > 0:
                    logger.info(f"WordPress token {token_id} revoked for user {user_id}")
                    return True
                return False
                
        except Exception as e:
            logger.error(f"Error revoking WordPress token: {e}")
            return False
    
    def get_connection_status(self, user_id: str) -> Dict[str, Any]:
        """Get WordPress connection status for a user."""
        try:
            tokens = self.get_user_tokens(user_id)
            
            if not tokens:
                return {
                    "connected": False,
                    "sites": [],
                    "total_sites": 0
                }
            
            # Test each token and get site information
            active_sites = []
            for token in tokens:
                if self.test_token(token["access_token"]):
                    active_sites.append({
                        "id": token["id"],
                        "blog_id": token["blog_id"],
                        "blog_url": token["blog_url"],
                        "scope": token["scope"],
                        "created_at": token["created_at"]
                    })
            
            return {
                "connected": len(active_sites) > 0,
                "sites": active_sites,
                "total_sites": len(active_sites)
            }
            
        except Exception as e:
            logger.error(f"Error getting WordPress connection status: {e}")
            return {
                "connected": False,
                "sites": [],
                "total_sites": 0
            }
