#!/usr/bin/env python3
"""
Activity Status Manager
Centralized module for tracking and updating real-time download activity status
Stores status in database for reliable, concurrent access

Supports:
- Single main activity (scheduler) via activity_status table
- Multiple background tasks (YouTube monitor, etc.) via background_task_status table
"""

import json
from datetime import datetime
from typing import Optional, Dict, Any, List
from pathlib import Path
from modules.universal_logger import get_logger

logger = get_logger('ActivityStatus')


class ActivityStatusManager:
    """Manages real-time activity status updates stored in database"""

    def __init__(self, unified_db=None):
        """
        Initialize activity status manager

        Args:
            unified_db: UnifiedDatabase instance (optional, will create if needed)
        """
        self.db = unified_db
        if not self.db:
            from modules.unified_database import UnifiedDatabase
            self.db = UnifiedDatabase()

        self._ensure_table()

    def _ensure_table(self):
        """Ensure activity_status and background_task_status tables exist"""
        try:
            with self.db.get_connection() as conn:
                cursor = conn.cursor()

                # Main scheduler activity table (single row)
                cursor.execute('''
                    CREATE TABLE IF NOT EXISTS activity_status (
                        id INTEGER PRIMARY KEY CHECK (id = 1),
                        active INTEGER NOT NULL DEFAULT 0,
                        task_id TEXT,
                        platform TEXT,
                        account TEXT,
                        start_time TEXT,
                        status TEXT,
                        detailed_status TEXT,
                        progress_current INTEGER,
                        progress_total INTEGER,
                        updated_at TEXT DEFAULT CURRENT_TIMESTAMP
                    )
                ''')

                # Add account progress columns if missing
                cursor.execute("PRAGMA table_info(activity_status)")
                columns = [col[1] for col in cursor.fetchall()]
                if 'account_current' not in columns:
                    cursor.execute('ALTER TABLE activity_status ADD COLUMN account_current INTEGER')
                if 'account_total' not in columns:
                    cursor.execute('ALTER TABLE activity_status ADD COLUMN account_total INTEGER')

                # Insert default row if doesn't exist
                cursor.execute('''
                    INSERT OR IGNORE INTO activity_status (id, active)
                    VALUES (1, 0)
                ''')

                # Background tasks table (multiple concurrent tasks like YouTube monitor)
                cursor.execute('''
                    CREATE TABLE IF NOT EXISTS background_task_status (
                        task_id TEXT PRIMARY KEY,
                        active INTEGER NOT NULL DEFAULT 0,
                        task_type TEXT,
                        display_name TEXT,
                        start_time TEXT,
                        status TEXT,
                        detailed_status TEXT,
                        progress_current INTEGER,
                        progress_total INTEGER,
                        extra_data TEXT,
                        updated_at TEXT DEFAULT CURRENT_TIMESTAMP
                    )
                ''')

                conn.commit()
        except Exception as e:
            logger.error(f"Failed to create activity tables: {e}")

    def start_activity(self, task_id: str, platform: str, account: str, status: str = "Running"):
        """
        Mark activity as started

        Args:
            task_id: Unique task identifier
            platform: Platform name (instagram, snapchat, etc)
            account: Account/username being processed
            status: Initial status message
        """
        try:
            with self.db.get_connection(for_write=True) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    UPDATE activity_status
                    SET active = 1,
                        task_id = ?,
                        platform = ?,
                        account = ?,
                        start_time = ?,
                        status = ?,
                        detailed_status = NULL,
                        progress_current = NULL,
                        progress_total = NULL,
                        account_current = NULL,
                        account_total = NULL,
                        updated_at = ?
                    WHERE id = 1
                ''', (task_id, platform, account, datetime.now().isoformat(),
                      status, datetime.now().isoformat()))
                conn.commit()
        except Exception as e:
            logger.error(f"Failed to start activity: {e}")

    def update_status(self, detailed_status: str, progress_current: Optional[int] = None,
                     progress_total: Optional[int] = None):
        """Update detailed status message and progress."""
        try:
            with self.db.get_connection(for_write=True) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    UPDATE activity_status
                    SET detailed_status = ?,
                        progress_current = COALESCE(?, progress_current),
                        progress_total = COALESCE(?, progress_total),
                        updated_at = ?
                    WHERE id = 1 AND active = 1
                ''', (detailed_status, progress_current, progress_total,
                      datetime.now().isoformat()))
                conn.commit()
        except Exception as e:
            logger.error(f"Failed to update status: {e}")

    def update_account_name(self, account: str):
        """Update the current account name being processed."""
        try:
            with self.db.get_connection(for_write=True) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    UPDATE activity_status
                    SET account = ?,
                        updated_at = ?
                    WHERE id = 1 AND active = 1
                ''', (account, datetime.now().isoformat()))
                conn.commit()
        except Exception as e:
            logger.error(f"Failed to update account name: {e}")

    def update_account_progress(self, account_current: int, account_total: int):
        """Update account-level progress and reset file-level progress for the new account"""
        try:
            with self.db.get_connection(for_write=True) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    UPDATE activity_status
                    SET account_current = ?,
                        account_total = ?,
                        progress_current = NULL,
                        progress_total = NULL,
                        updated_at = ?
                    WHERE id = 1 AND active = 1
                ''', (account_current, account_total, datetime.now().isoformat()))
                conn.commit()
        except Exception as e:
            logger.error(f"Failed to update account progress: {e}")

    def stop_activity(self):
        """Mark activity as stopped"""
        try:
            with self.db.get_connection(for_write=True) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    UPDATE activity_status
                    SET active = 0,
                        detailed_status = NULL,
                        progress_current = NULL,
                        progress_total = NULL,
                        account_current = NULL,
                        account_total = NULL,
                        updated_at = ?
                    WHERE id = 1
                ''', (datetime.now().isoformat(),))
                conn.commit()
        except Exception as e:
            logger.error(f"Failed to stop activity: {e}")

    def get_current_activity(self) -> Dict[str, Any]:
        """
        Get current activity status

        Returns:
            Dict with activity information
        """
        try:
            with self.db.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    SELECT active, task_id, platform, account, start_time, status,
                           detailed_status, progress_current, progress_total,
                           account_current, account_total
                    FROM activity_status
                    WHERE id = 1
                ''')
                row = cursor.fetchone()

                if row:
                    result = {
                        'active': bool(row[0]),
                        'task_id': row[1],
                        'platform': row[2],
                        'account': row[3],
                        'start_time': row[4],
                        'status': row[5]
                    }

                    # Add optional fields only if they exist
                    if row[6]:  # detailed_status
                        result['detailed_status'] = row[6]
                    if row[7] is not None and row[8] is not None:  # progress
                        result['progress'] = {
                            'current': row[7],
                            'total': row[8]
                        }
                    if row[9] is not None and row[10] is not None:  # account_progress
                        result['account_progress'] = {
                            'current': row[9],
                            'total': row[10]
                        }

                    return result

                return {
                    'active': False,
                    'task_id': None,
                    'platform': None,
                    'account': None,
                    'start_time': None,
                    'status': None
                }
        except Exception as e:
            logger.error(f"Failed to get current activity: {e}")
            return {
                'active': False,
                'task_id': None,
                'platform': None,
                'account': None,
                'start_time': None,
                'status': None
            }

    # =========================================================================
    # BACKGROUND TASK METHODS (for concurrent tasks like YouTube monitor)
    # =========================================================================

    def start_background_task(self, task_id: str, task_type: str, display_name: str,
                               status: str = "Running", extra_data: Dict = None):
        """
        Start a background task (doesn't interfere with main activity).

        Args:
            task_id: Unique task identifier (e.g., 'youtube_monitor')
            task_type: Type of task (e.g., 'youtube_monitor', 'video_processor')
            display_name: Human-readable name for display
            status: Initial status message
            extra_data: Optional extra data to store as JSON
        """
        try:
            with self.db.get_connection(for_write=True) as conn:
                cursor = conn.cursor()
                # Check if task is already running - don't reset if so
                cursor.execute('''
                    SELECT active FROM background_task_status WHERE task_id = ?
                ''', (task_id,))
                row = cursor.fetchone()
                if row and row[0] == 1:
                    # Task already running, just update status without resetting counter
                    logger.debug(f"Background task {task_id} already running, not resetting")
                    return

                cursor.execute('''
                    INSERT OR REPLACE INTO background_task_status
                    (task_id, active, task_type, display_name, start_time, status,
                     detailed_status, progress_current, progress_total, extra_data, updated_at)
                    VALUES (?, 1, ?, ?, ?, ?, NULL, NULL, NULL, ?, ?)
                ''', (task_id, task_type, display_name, datetime.now().isoformat(),
                      status, json.dumps(extra_data) if extra_data else None,
                      datetime.now().isoformat()))
                conn.commit()
        except Exception as e:
            logger.error(f"Failed to start background task {task_id}: {e}")

    def update_background_task(self, task_id: str, detailed_status: str,
                                progress_current: Optional[int] = None,
                                progress_total: Optional[int] = None,
                                extra_data: Dict = None):
        """Update a background task's status."""
        try:
            with self.db.get_connection(for_write=True) as conn:
                cursor = conn.cursor()
                if extra_data is not None:
                    cursor.execute('''
                        UPDATE background_task_status
                        SET detailed_status = ?,
                            progress_current = ?,
                            progress_total = ?,
                            extra_data = ?,
                            updated_at = ?
                        WHERE task_id = ? AND active = 1
                    ''', (detailed_status, progress_current, progress_total,
                          json.dumps(extra_data), datetime.now().isoformat(), task_id))
                else:
                    cursor.execute('''
                        UPDATE background_task_status
                        SET detailed_status = ?,
                            progress_current = ?,
                            progress_total = ?,
                            updated_at = ?
                        WHERE task_id = ? AND active = 1
                    ''', (detailed_status, progress_current, progress_total,
                          datetime.now().isoformat(), task_id))
                conn.commit()
        except Exception as e:
            logger.error(f"Failed to update background task {task_id}: {e}")

    def stop_background_task(self, task_id: str):
        """Mark a background task as stopped."""
        try:
            with self.db.get_connection(for_write=True) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    UPDATE background_task_status
                    SET active = 0,
                        updated_at = ?
                    WHERE task_id = ?
                ''', (datetime.now().isoformat(), task_id))
                conn.commit()
        except Exception as e:
            logger.error(f"Failed to stop background task {task_id}: {e}")

    def stop_all_background_tasks(self):
        """Mark all background tasks as stopped (used on scheduler startup to clear stale state)."""
        try:
            with self.db.get_connection(for_write=True) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    UPDATE background_task_status
                    SET active = 0,
                        updated_at = ?
                    WHERE active = 1
                ''', (datetime.now().isoformat(),))
                count = cursor.rowcount
                conn.commit()
                if count > 0:
                    logger.info(f"Cleared {count} stale background task(s) from previous run")
        except Exception as e:
            logger.error(f"Failed to stop all background tasks: {e}")

    def get_background_task(self, task_id: str) -> Optional[Dict[str, Any]]:
        """
        Get a specific background task's status.

        Args:
            task_id: Task identifier

        Returns:
            Dict with task information or None
        """
        try:
            with self.db.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    SELECT task_id, active, task_type, display_name, start_time,
                           status, detailed_status, progress_current, progress_total,
                           extra_data, updated_at
                    FROM background_task_status
                    WHERE task_id = ?
                ''', (task_id,))
                row = cursor.fetchone()

                if row:
                    result = {
                        'task_id': row[0],
                        'active': bool(row[1]),
                        'task_type': row[2],
                        'display_name': row[3],
                        'start_time': row[4],
                        'status': row[5],
                        'updated_at': row[10]
                    }

                    if row[6]:  # detailed_status
                        result['detailed_status'] = row[6]
                    if row[7] is not None and row[8] is not None:  # progress
                        result['progress'] = {
                            'current': row[7],
                            'total': row[8]
                        }
                    if row[9]:  # extra_data
                        try:
                            result['extra_data'] = json.loads(row[9])
                        except (json.JSONDecodeError, TypeError, ValueError) as e:
                            logger.debug(f"Failed to parse extra_data for task {task_id}: {e}")
                            result['extra_data'] = {}

                    return result
                return None
        except Exception as e:
            logger.error(f"Failed to get background task {task_id}: {e}")
            return None

    def get_active_background_tasks(self) -> List[Dict[str, Any]]:
        """
        Get all active background tasks.

        Returns:
            List of active task dictionaries
        """
        try:
            with self.db.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    SELECT task_id, active, task_type, display_name, start_time,
                           status, detailed_status, progress_current, progress_total,
                           extra_data, updated_at
                    FROM background_task_status
                    WHERE active = 1
                    ORDER BY start_time DESC
                ''')

                tasks = []
                for row in cursor.fetchall():
                    task = {
                        'task_id': row[0],
                        'active': bool(row[1]),
                        'task_type': row[2],
                        'display_name': row[3],
                        'start_time': row[4],
                        'status': row[5],
                        'updated_at': row[10]
                    }

                    if row[6]:  # detailed_status
                        task['detailed_status'] = row[6]
                    if row[7] is not None and row[8] is not None:  # progress
                        task['progress'] = {
                            'current': row[7],
                            'total': row[8]
                        }
                    if row[9]:  # extra_data
                        try:
                            task['extra_data'] = json.loads(row[9])
                        except (json.JSONDecodeError, TypeError, ValueError):
                            task['extra_data'] = {}

                    tasks.append(task)

                return tasks
        except Exception as e:
            logger.error(f"Failed to get active background tasks: {e}")
            return []


# Global instance with thread-safe initialization
_activity_manager = None
_activity_manager_lock = __import__('threading').Lock()


def get_activity_manager(unified_db=None):
    """Get or create global activity manager instance (thread-safe)"""
    global _activity_manager
    if _activity_manager is None:
        with _activity_manager_lock:
            # Double-check inside lock to prevent race condition
            if _activity_manager is None:
                _activity_manager = ActivityStatusManager(unified_db)
    return _activity_manager
