"""
Queue-based worker functions for the stress policy tool.

This module contains worker functions that process tasks from Redis queues
instead of files, supporting both authentication and download workflows.
"""

import json
import logging
import os
import random
import re
import shlex
import sys
import tempfile
import shutil
import threading
import time
from copy import deepcopy
from datetime import datetime, timezone
from pathlib import Path
from typing import Dict, List, Optional, Any, Tuple, Union

from . import utils as sp_utils
from .process_runners import run_command, run_docker_container, get_worker_id
from .workers import get_auth_manager
from .queue_provider import RedisQueueProvider

logger = logging.getLogger(__name__)


def run_queue_auth_worker(worker_id, policy, state_manager, args, profile_manager_instance, running_processes, process_lock):
    """Worker function for processing authentication tasks from a queue in batches."""
    owner_id = f"queue-auth-worker-{worker_id}"
    settings = policy.get('settings', {})
    exec_control = policy.get('execution_control', {})
    gen_policy = policy.get('info_json_generation_policy', {})
    queue_policy = policy.get('queue_policy', {})

    profile_prefix = gen_policy.get('profile_prefix')
    if not profile_prefix:
        logger.error(f"[Worker {worker_id}] Queue auth mode requires 'info_json_generation_policy.profile_prefix'. Worker exiting.")
        return []

    save_dir = settings.get('save_info_json_dir')
    if not save_dir and queue_policy.get('formats_to_download'):
        save_dir = os.path.join('run', 'stress_policy', 'info_jsons')
        logger.info(f"[Worker {worker_id}] 'formats_to_download' is set and 'save_info_json_dir' is not, defaulting to '{save_dir}'")

    if save_dir:
        os.makedirs(save_dir, exist_ok=True)
        logger.info(f"[Worker {worker_id}] Will save info.json files to '{save_dir}'")

    batch_size = queue_policy.get('batch_size', 1)
    logger.info(f"[Worker {worker_id}] Auth worker configured to process tasks in batches of {batch_size}.")
    task_counter = 0

    while not state_manager.shutdown_event.is_set():
        locked_profile = None
        tasks = []
        
        try:
            # 1. Lock a profile FIRST
            locked_profile = profile_manager_instance.lock_profile(owner=owner_id, profile_prefix=profile_prefix)
            if not locked_profile:
                polling_interval = exec_control.get('worker_polling_interval_seconds', 1)
                logger.debug(f"[Worker {worker_id}] No profiles available to lock. Sleeping for {polling_interval}s.")
                time.sleep(polling_interval)
                continue

            profile_name = locked_profile['name']
            proxy_url = locked_profile['proxy']

            # 2. Get a batch of tasks from the queue
            tasks = state_manager.get_auth_tasks_batch(batch_size)
            if not tasks:
                polling_interval = exec_control.get('worker_polling_interval_seconds', 1)
                logger.debug(f"[Worker {worker_id}] No tasks available for profile '{profile_name}'. Unlocking and sleeping for {polling_interval}s.")
                # Unlock immediately since we have no work to do.
                # No cooldown is applied here to make the profile available again quickly.
                profile_manager_instance.unlock_profile(profile_name, owner=owner_id)
                locked_profile = None # To prevent double-unlock in finally
                time.sleep(polling_interval)
                continue

            logger.info(f"[Worker {worker_id}] Locked profile '{profile_name}' to process a batch of {len(tasks)} tasks.")

            # 3. Process each task in the batch
            for task in tasks:
                if state_manager.shutdown_event.is_set():
                    logger.info(f"[Worker {worker_id}] Shutdown requested, stopping batch processing for profile '{profile_name}'.")
                    break

                temp_task_dir = None
                task_id = None
                url = None
                try:
                    temp_task_dir = tempfile.mkdtemp(prefix=f"queue-auth-{worker_id}-")
                    task_id = task.get('id') or task.get('task_id')
                    if not task_id:
                        task_id = f"task_{worker_id}_{task_counter}"
                        task_counter += 1
                        task['task_id'] = task_id
                    
                    url = task.get('url')
                    if not url:
                        logger.error(f"[Worker {worker_id}] Task {task_id} has no URL. Skipping.")
                        state_manager.report_auth_skipped(task_id, {"error": "No URL in task", "task": task})
                        continue
                    
                    logger.info(f"[Worker {worker_id}] [{profile_name}] Processing task {task_id}: {url}")
                    state_manager.mark_auth_in_progress(task_id, owner_id)

                    # --- Main processing logic for a single task ---
                    success, info_data, stderr, retcode = False, None, "", 0
                    if args.dummy or args.dummy_batch:
                        logger.info(f"[Worker {worker_id}] [{profile_name}] DUMMY MODE: Simulating auth for {url}")
                        dummy_settings = policy.get('settings', {}).get('dummy_simulation_settings', {})
                        min_seconds = dummy_settings.get('auth_min_seconds', 0.1)
                        max_seconds = dummy_settings.get('auth_max_seconds', 0.5)
                        failure_rate = args.dummy_auth_failure_rate or dummy_settings.get('auth_failure_rate', 0.0)
                        skipped_rate = args.dummy_auth_skipped_failure_rate or dummy_settings.get('auth_skipped_failure_rate', 0.0)
                        time.sleep(random.uniform(min_seconds, max_seconds))

                        rand_val = random.random()
                        if rand_val < skipped_rate:
                            stderr = "Dummy skipped failure"
                        elif rand_val < (skipped_rate + failure_rate):
                            stderr = "Dummy fatal failure"
                        else:
                            success = True
                            video_id = sp_utils.get_video_id(url) or f"dummy_{random.randint(1000, 9999)}"
                            info_data = {'id': video_id, 'title': f'Dummy Video {video_id}', '_dummy': True, 'formats': [{'format_id': '18'}, {'format_id': '140'}]}
                    else:
                        client, req_params = state_manager.get_client_for_request(profile_name, gen_policy)
                        cmd = [
                            sys.executable, '-m', 'ytops_client.cli', 'get-info',
                            '--client', client, '--profile', profile_name
                        ]
                        if proxy_url:
                            cmd.extend(['--proxy', proxy_url])
                        if req_params:
                            cmd.extend(['--request-params', json.dumps(req_params)])
                        extra_args = gen_policy.get('extra_args')
                        if extra_args:
                            cmd.extend(shlex.split(extra_args))
                        
                        # The URL must be the last positional argument
                        cmd.append(url)
                        
                        logger.info(f"[Worker {worker_id}] Running command: {' '.join(shlex.quote(s) for s in cmd)}")
                        retcode, stdout, stderr = run_command(
                            cmd, running_processes, process_lock, stream_output=args.verbose,
                            stream_prefix=f"[Worker {worker_id} | get-info] "
                        )
                        success = (retcode == 0)
                        if success:
                            info_json_path = next((line.strip() for line in stdout.strip().split('\n') if line.endswith('.json') and os.path.exists(line.strip())), None)
                            if info_json_path:
                                try:
                                    with open(info_json_path, 'r', encoding='utf-8') as f:
                                        info_data = json.load(f)
                                except (IOError, json.JSONDecodeError) as e:
                                    logger.error(f"[Worker {worker_id}] Failed to read/parse info.json from get-info: {e}")
                                    success = False
                                    stderr += f"\nFailed to read/parse info.json: {e}"
                            else:
                                logger.error(f"[Worker {worker_id}] Command succeeded but no info.json path found in output.")
                                success = False
                                stderr += "\nNo info.json path in output"

                    # --- Result processing for a single task ---
                    if success and info_data:
                        try:
                            auth_env_name = profile_manager_instance.key_prefix.replace('_profile_mgmt_', '')
                            info_data['_ytops_metadata'] = {
                                'profile_name': profile_name, 'proxy_url': proxy_url,
                                'generation_timestamp_utc': datetime.now(timezone.utc).isoformat(),
                                'task_id': task_id, 'url': url, 'auth_env': auth_env_name
                            }
                            
                            final_path = None
                            if save_dir:
                                video_id = info_data.get('id', 'unknown')
                                sanitized_proxy = re.sub(r'[:/]', '_', proxy_url) if proxy_url else 'noproxy'
                                new_name = f"{video_id}-{profile_name}-{sanitized_proxy}.json"
                                final_path = os.path.join(save_dir, new_name)
                                with open(final_path, 'w', encoding='utf-8') as f:
                                    json.dump(info_data, f, indent=2)
                                logger.info(f"[Worker {worker_id}] [{profile_name}] Saved info.json to '{final_path}'")
                            else:
                                # This case means auth-only (no downloads) and no save_dir specified.
                                # The info.json is not persisted.
                                logger.debug(f"[Worker {worker_id}] [{profile_name}] Auth-only task succeeded. No save_dir, so info.json is not saved.")

                            profile_manager_instance.record_activity(profile_name, 'success')
                            
                            formats_to_download = queue_policy.get('formats_to_download')
                            download_tasks = []
                            if formats_to_download:
                                task_formats = []
                                if formats_to_download == 'all':
                                    task_formats = [f['format_id'] for f in info_data.get('formats', [])]
                                elif isinstance(formats_to_download, list):
                                    task_formats = formats_to_download
                                else:
                                    task_formats = [str(formats_to_download)]
                                
                                for format_id in task_formats:
                                    download_tasks.append({
                                        'info_json_path': final_path, 'format_id': format_id,
                                        'video_id': info_data.get('id'), 'url': url,
                                        'auth_profile_name': profile_name, 'proxy_url': proxy_url,
                                        'auth_env': auth_env_name,
                                        'original_task': task
                                    })
                            
                            if download_tasks:
                                added_count = state_manager.add_download_tasks_batch(download_tasks)
                                logger.info(f"[Worker {worker_id}] [{profile_name}] Added {added_count} download tasks to queue")
                                profile_manager_instance.increment_pending_downloads(profile_name, count=added_count)
                            
                            state_manager.report_auth_success(task_id, {
                                "url": url, "video_id": info_data.get('id'), "profile_name": profile_name,
                                "proxy_url": proxy_url, "info_json_path": final_path,
                                "download_tasks_created": len(download_tasks)
                            })
                        except Exception as e:
                            logger.error(f"[Worker {worker_id}] [{profile_name}] Error processing successful auth result: {e}", exc_info=True)
                            profile_manager_instance.record_activity(profile_name, 'failure')
                            state_manager.report_auth_failure(task_id, {"error": f"Error processing info.json: {str(e)}", "url": url})
                    else:
                        is_bot_error = "Sign in to confirm you're not a bot" in stderr
                        is_timeout_error = "Read timed out" in stderr
                        is_unavailable = "This video is unavailable" in stderr or "Video unavailable" in stderr
                        is_private = "This video is private" in stderr or "Private video" in stderr
                        is_deleted = "This video has been removed" in stderr
                        is_dummy_skipped = "Dummy skipped failure" in stderr
                        
                        if is_unavailable or is_private or is_deleted or is_dummy_skipped:
                            reason = "Video unavailable" if is_unavailable else "Private video" if is_private else "Video removed" if is_deleted else "Dummy skipped"
                            logger.warning(f"[Worker {worker_id}] [{profile_name}] Auth skipped for {url}: {reason}")
                            profile_manager_instance.record_activity(profile_name, 'tolerated_error')
                            state_manager.report_auth_skipped(task_id, {"url": url, "reason": reason, "stderr": stderr})
                        else:
                            error_type = "Bot detection" if is_bot_error else "Timeout" if is_timeout_error else "Dummy fatal failure" if "Dummy fatal failure" in stderr else f"Exit code {retcode}"
                            logger.error(f"[Worker {worker_id}] [{profile_name}] Authentication failed ({error_type}): {url}")
                            profile_manager_instance.record_activity(profile_name, 'failure')
                            state_manager.report_auth_failure(task_id, {"url": url, "error_type": error_type, "stderr": stderr, "exit_code": retcode})

                except Exception as e:
                    logger.error(f"[Worker {worker_id}] [{profile_name}] Unexpected error processing task {task_id}: {e}", exc_info=True)
                    if task_id:
                        state_manager.report_auth_failure(task_id, {"error": f"Unexpected error: {str(e)}", "url": url or "unknown"})
                    profile_manager_instance.record_activity(profile_name, 'failure')
                finally:
                    if temp_task_dir and os.path.exists(temp_task_dir):
                        shutil.rmtree(temp_task_dir)
                    if task_id:
                        state_manager.remove_auth_in_progress(task_id)
        
        except Exception as e:
            logger.error(f"[Worker {worker_id}] Unexpected error in outer worker loop: {e}", exc_info=True)
            if locked_profile:
                profile_manager_instance.record_activity(locked_profile['name'], 'failure')
        
        finally:
            if locked_profile:
                cooldown = None
                cooldown_config = profile_manager_instance.get_config('unlock_cooldown_seconds')
                if cooldown_config:
                    try:
                        val = json.loads(cooldown_config)
                        if isinstance(val, list) and len(val) == 2 and val[0] < val[1]:
                            cooldown = random.randint(val[0], val[1])
                        elif isinstance(val, int):
                            cooldown = val
                    except (json.JSONDecodeError, TypeError):
                        if cooldown_config.isdigit():
                            cooldown = int(cooldown_config)

                if cooldown:
                    logger.info(f"[Worker {worker_id}] Putting profile '{locked_profile['name']}' into COOLDOWN for {cooldown}s.")

                profile_manager_instance.unlock_profile(
                    locked_profile['name'],
                    owner=owner_id,
                    rest_for_seconds=cooldown
                )

    logger.info(f"[Worker {worker_id}] Queue auth worker exiting.")
    return []


def run_queue_download_worker(worker_id, policy, state_manager, args, profile_manager_instance, running_processes, process_lock):
    """Worker function for processing download tasks from a queue."""
    owner_id = f"queue-dl-worker-{worker_id}"
    settings = policy.get('settings', {})
    exec_control = policy.get('execution_control', {})
    d_policy = policy.get('download_policy', {})
    queue_policy = policy.get('queue_policy', {})

    profile_prefix = d_policy.get('profile_prefix')
    if not profile_prefix:
        logger.error(f"[Worker {worker_id}] Queue download mode requires 'download_policy.profile_prefix'. Worker exiting.")
        return []

    output_dir = d_policy.get('output_dir')
    if output_dir:
        os.makedirs(output_dir, exist_ok=True)
        logger.info(f"[Worker {worker_id}] Will save downloads to '{output_dir}'")
    
    task_counter = 0
    
    while not state_manager.shutdown_event.is_set():
        locked_profile = None
        temp_task_dir = None
        task = None
        auth_profile_name, auth_env = None, None
        
        try:
            task = state_manager.get_download_task()
            if not task:
                polling_interval = exec_control.get('worker_polling_interval_seconds', 1)
                logger.debug(f"[Worker {worker_id}] No download tasks available in queue. Sleeping for {polling_interval}s.")
                time.sleep(polling_interval)
                continue
            
            task_id = task.get('id') or task.get('task_id')
            if not task_id:
                task_id = f"dl_task_{worker_id}_{task_counter}"
                task_counter += 1
                task['task_id'] = task_id
            
            info_json_path = task.get('info_json_path')
            format_id = task.get('format_id')
            video_id = task.get('video_id')
            url = task.get('url')
            
            # Get auth metadata for decrementing counter later.
            # Primary source is the task itself. Fallback to info.json for older tasks.
            auth_profile_name = task.get('auth_profile_name')
            auth_env = task.get('auth_env')

            if (not auth_profile_name or not auth_env):
                if info_json_path and os.path.exists(info_json_path):
                    try:
                        with open(info_json_path, 'r', encoding='utf-8') as f:
                            info_data = json.load(f)
                        metadata = info_data.get('_ytops_metadata', {})
                        auth_profile_name = auth_profile_name or metadata.get('profile_name')
                        auth_env = auth_env or metadata.get('auth_env')
                        logger.debug(f"Read auth metadata from info.json fallback: profile={auth_profile_name}, env={auth_env}")
                    except (IOError, json.JSONDecodeError) as e:
                        logger.warning(f"[Worker {worker_id}] Could not read info.json to get auth metadata: {e}")
                else:
                    logger.warning(f"[Worker {worker_id}] Task missing auth metadata and info.json is missing or not specified. Pending downloads counter will not be decremented.")

            # In dummy mode, the info.json file doesn't need to exist locally.
            if not (args.dummy or args.dummy_batch):
                if not info_json_path or not os.path.exists(info_json_path):
                    logger.error(f"[Worker {worker_id}] Task {task_id} has invalid info_json_path: {info_json_path}. Skipping.")
                    state_manager.report_download_skipped(task_id, {"error": "Invalid info_json_path", "task": task})
                    # The finally block will handle decrementing the pending downloads counter.
                    continue
            
            if not format_id:
                logger.error(f"[Worker {worker_id}] Task {task_id} has no format_id. Skipping.")
                state_manager.report_download_skipped(task_id, {"error": "No format_id in task", "task": task})
                continue
            
            
            logger.info(f"[Worker {worker_id}] Processing download task {task_id}: {video_id or url} format {format_id}")
            state_manager.mark_download_in_progress(task_id, owner_id)
            
            specific_profile = task.get('auth_profile_name') or task.get('profile_name') # 'profile_name' for backward compatibility
            if specific_profile:
                locked_profile = profile_manager_instance.lock_profile(owner=owner_id, specific_profile_name=specific_profile)
                if not locked_profile:
                    logger.warning(f"[Worker {worker_id}] Could not lock specific profile '{specific_profile}'. Trying any profile with prefix.")
                    locked_profile = profile_manager_instance.lock_profile(owner=owner_id, profile_prefix=profile_prefix)
            else:
                locked_profile = profile_manager_instance.lock_profile(owner=owner_id, profile_prefix=profile_prefix)
            
            if not locked_profile:
                polling_interval = exec_control.get('worker_polling_interval_seconds', 1)
                logger.warning(f"[Worker {worker_id}] No profiles available for task {task_id}. Re-queueing and sleeping for {polling_interval}s.")
                # Re-queue the task by adding it back to the inbox.
                state_manager.add_download_tasks_batch([task])
                # The 'in_progress' marker for this attempt will be cleaned up by the finally block.
                time.sleep(polling_interval)
                continue
            
            profile_name = locked_profile['name']
            proxy_url = locked_profile['proxy']
            logger.info(f"[Worker {worker_id}] Locked profile '{profile_name}' with proxy '{proxy_url}'")
            
            temp_task_dir = tempfile.mkdtemp(prefix=f"queue-dl-{worker_id}-")
            success = False
            downloaded_filepath = None
            stderr = ""

            if args.dummy or args.dummy_batch:
                logger.info(f"[Worker {worker_id}] [{profile_name}] DUMMY MODE: Simulating download for {video_id or url} format {format_id}")
                dummy_settings = policy.get('settings', {}).get('dummy_simulation_settings', {})
                min_seconds = dummy_settings.get('download_min_seconds', 1.0)
                max_seconds = dummy_settings.get('download_max_seconds', 3.0)
                failure_rate = dummy_settings.get('download_failure_rate', 0.0)
                skipped_rate = dummy_settings.get('download_skipped_failure_rate', 0.0)
                time.sleep(random.uniform(min_seconds, max_seconds))

                rand_val = random.random()
                if rand_val < skipped_rate:
                    stderr = "Dummy skipped failure"
                elif rand_val < (skipped_rate + failure_rate):
                    stderr = "Dummy fatal failure"
                else:
                    success = True
                    downloaded_filepath = f"/dev/null/{video_id}.mp4"
                    # In dummy mode, the info.json is a read-only artifact, just like in
                    # the non-dummy Airflow path. It is not renamed or deleted to avoid
                    # race conditions between workers processing different formats for the
                    # same video. The files can be cleaned up manually between runs.
            else:
                cmd = [
                    sys.executable, '-m', 'ytops_client.cli', 'download', 'py',
                    '--load-info-json', info_json_path,
                    '-f', format_id
                ]
                if proxy_url:
                    cmd.extend(['--proxy', proxy_url])
                if output_dir:
                    cmd.extend(['--output-dir', output_dir])
                extra_args = d_policy.get('extra_args')
                if extra_args:
                    cmd.extend(shlex.split(extra_args))
                
                logger.info(f"[Worker {worker_id}] Running command: {' '.join(shlex.quote(s) for s in cmd)}")
                retcode, stdout, stderr = run_command(
                    cmd, running_processes, process_lock, stream_output=args.verbose,
                    stream_prefix=f"[Worker {worker_id} | download] "
                )
                success = (retcode == 0)
                if success:
                    for line in stdout.strip().split('\n'):
                        if os.path.exists(line.strip()):
                            downloaded_filepath = line.strip()
                            break

            if success:
                # --- Airflow Integration ---
                if d_policy.get('output_to_airflow_ready_dir'):
                    base_path = d_policy.get('airflow_ready_dir_base_path')
                    if not base_path:
                        logger.error(f"[Worker {worker_id}] 'output_to_airflow_ready_dir' is true but 'airflow_ready_dir_base_path' is not set. Skipping Airflow output.")
                    else:
                        try:
                            # Create a unique, timestamped directory for the video
                            ts = datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S_%f')
                            final_dir = os.path.join(base_path, ts + '_' + (video_id or 'unknown_video'))
                            os.makedirs(final_dir, exist_ok=True)

                            # Copy info.json to avoid a race condition where multiple download workers
                            # for different formats try to move the same source file.
                            if info_json_path and os.path.exists(info_json_path):
                                final_info_json_path = os.path.join(final_dir, os.path.basename(info_json_path))
                                shutil.copy(info_json_path, final_info_json_path)
                                logger.info(f"[Worker {worker_id}] Copied info.json to Airflow-ready dir: {final_info_json_path}")
                                # Update the path for reporting to point to the new copy
                                info_json_path = final_info_json_path
                            
                            # Move downloaded file (if not in dummy mode)
                            if downloaded_filepath and os.path.exists(downloaded_filepath):
                                final_media_path = os.path.join(final_dir, os.path.basename(downloaded_filepath))
                                shutil.move(downloaded_filepath, final_media_path)
                                logger.info(f"[Worker {worker_id}] Moved media file to Airflow-ready dir: {final_media_path}")
                                # Update the path for reporting
                                downloaded_filepath = final_media_path

                        except Exception as e:
                            logger.error(f"[Worker {worker_id}] Failed to move files to Airflow-ready directory: {e}", exc_info=True)

                profile_manager_instance.record_activity(profile_name, 'download_success')
                state_manager.report_download_success(task_id, {
                    "video_id": video_id, "url": url, "format_id": format_id,
                    "profile_name": profile_name, "proxy_url": proxy_url,
                    "downloaded_filepath": downloaded_filepath, "info_json_path": info_json_path
                })
                logger.info(f"[Worker {worker_id}] Download successful: {video_id or url} format {format_id}")

                # --- Rename source info.json to mark as processed ---
                if d_policy.get('rename_source_info_json_on_success'):
                    # Use the original path from the task, as the `info_json_path` variable
                    # may have been updated by the Airflow logic to point to a copy.
                    source_path_to_rename = task.get('info_json_path')
                    if source_path_to_rename and os.path.exists(source_path_to_rename):
                        try:
                            processed_path = source_path_to_rename + ".processed"
                            shutil.move(source_path_to_rename, processed_path)
                            logger.info(f"[Worker {worker_id}] Renamed source info.json to '{processed_path}'")
                        except Exception as e:
                            logger.warning(f"[Worker {worker_id}] Could not rename source info.json '{source_path_to_rename}': {e}")
            else:
                is_bot_error = "Sign in to confirm you're not a bot" in stderr
                is_timeout_error = "Read timed out" in stderr
                is_unavailable = "This video is unavailable" in stderr or "Video unavailable" in stderr
                is_format_error = "requested format not available" in stderr
                
                if is_unavailable or is_format_error:
                    logger.warning(f"[Worker {worker_id}] Download skipped: {video_id or url} format {format_id}")
                    profile_manager_instance.record_activity(profile_name, 'tolerated_error')
                    state_manager.report_download_skipped(task_id, {
                        "video_id": video_id, "url": url, "format_id": format_id,
                        "reason": "Video unavailable" if is_unavailable else "Format not available", "stderr": stderr
                    })
                else:
                    error_type = "Bot detection" if is_bot_error else "Timeout" if is_timeout_error else f"Exit code {retcode}"
                    logger.error(f"[Worker {worker_id}] Download failed ({error_type}): {video_id or url} format {format_id}")
                    profile_manager_instance.record_activity(profile_name, 'download_error')
                    state_manager.report_download_failure(task_id, {
                        "video_id": video_id, "url": url, "format_id": format_id,
                        "error_type": error_type, "stderr": stderr, "exit_code": retcode,
                        "original_task": task
                    })

            # Decrement pending downloads counter on the original auth profile, regardless of outcome
            if auth_profile_name and auth_env:
                auth_manager = get_auth_manager(profile_manager_instance, auth_env)
                if auth_manager:
                    auth_manager.decrement_pending_downloads(auth_profile_name)
                else:
                    logger.error(f"Could not get auth profile manager for env '{auth_env}'. Pending downloads counter will not be decremented.")
            elif task: # Only warn if we had a task but couldn't get metadata
                logger.warning(f"Could not find auth profile name and/or auth_env in info.json metadata. Pending downloads counter will not be decremented.")
        
        except Exception as e:
            logger.error(f"[Worker {worker_id}] Unexpected error: {e}", exc_info=True)
            if task and task_id:
                state_manager.report_download_failure(task_id, {
                    "video_id": video_id if 'video_id' in locals() else "unknown",
                    "url": url if 'url' in locals() else "unknown",
                    "format_id": format_id if 'format_id' in locals() else "unknown",
                    "error": f"Unexpected error: {str(e)}", "original_task": task
                })
            if locked_profile:
                profile_manager_instance.record_activity(locked_profile['name'], 'download_error')
        
        finally:
            if locked_profile:
                cooldown = None
                cooldown_config = profile_manager_instance.get_config('unlock_cooldown_seconds')
                if cooldown_config:
                    try:
                        val = json.loads(cooldown_config)
                        if isinstance(val, list) and len(val) == 2 and val[0] < val[1]:
                            cooldown = random.randint(val[0], val[1])
                        elif isinstance(val, int):
                            cooldown = val
                    except (json.JSONDecodeError, TypeError):
                        if cooldown_config.isdigit():
                            cooldown = int(cooldown_config)

                if cooldown:
                    logger.info(f"[Worker {worker_id}] Putting profile '{locked_profile['name']}' into COOLDOWN for {cooldown}s.")

                profile_manager_instance.unlock_profile(
                    locked_profile['name'],
                    owner=owner_id,
                    rest_for_seconds=cooldown
                )
            
            if temp_task_dir and os.path.exists(temp_task_dir):
                shutil.rmtree(temp_task_dir)
            
            if task and task_id:
                state_manager.remove_download_in_progress(task_id)
    
    logger.info(f"[Worker {worker_id}] Queue download worker exiting.")
    return []
