import os

from flask import Blueprint, request, jsonify
from datetime import datetime, timedelta
from tinydb import Query

from db.db import users_db
from models.user import User
from api.utils import admin_required, get_validated_user_id
from config.deletion_config import (
    ACCOUNT_DELETION_THRESHOLD_HOURS,
    MIN_THRESHOLD_HOURS,
    MAX_THRESHOLD_HOURS,
    validate_threshold
)
from utils.account_deletion_scheduler import trigger_deletion_manually

admin_api = Blueprint('admin_api', __name__)


@admin_api.route('/admin/deletion-queue', methods=['GET'])
@admin_required
def get_deletion_queue():
    """
    Get list of users pending deletion.
    Returns users marked for deletion with their deletion due dates.
    """
    try:
        Query_ = Query()
        marked_users = users_db.search(Query_.marked_for_deletion == True)
        
        users_data = []
        for user_dict in marked_users:
            user = User.from_dict(user_dict)
            
            # Calculate deletion_due_at
            deletion_due_at = None
            if user.marked_for_deletion_at:
                try:
                    marked_at = datetime.fromisoformat(user.marked_for_deletion_at)
                    due_at = marked_at + timedelta(hours=ACCOUNT_DELETION_THRESHOLD_HOURS)
                    deletion_due_at = due_at.isoformat()
                except (ValueError, TypeError):
                    pass
            
            users_data.append({
                'id': user.id,
                'email': user.email,
                'marked_for_deletion_at': user.marked_for_deletion_at,
                'deletion_due_at': deletion_due_at,
                'deletion_in_progress': user.deletion_in_progress,
                'deletion_attempted_at': user.deletion_attempted_at
            })
        
        return jsonify({
            'count': len(users_data),
            'users': users_data
        }), 200
        
    except Exception as e:
        return jsonify({'error': str(e), 'code': 'SERVER_ERROR'}), 500

@admin_api.route('/admin/deletion-threshold', methods=['GET'])
@admin_required
def get_deletion_threshold():
    """
    Get current deletion threshold configuration.
    """
    return jsonify({
        'threshold_hours': ACCOUNT_DELETION_THRESHOLD_HOURS,
        'threshold_min': MIN_THRESHOLD_HOURS,
        'threshold_max': MAX_THRESHOLD_HOURS
    }), 200

@admin_api.route('/admin/deletion-threshold', methods=['PUT'])
@admin_required
def update_deletion_threshold():
    """
    Update deletion threshold.
    Note: This updates the runtime value but doesn't persist to environment variables.
    For permanent changes, update the ACCOUNT_DELETION_THRESHOLD_HOURS env variable.
    """
    try:
        data = request.get_json()
        
        if not data or 'threshold_hours' not in data:
            return jsonify({
                'error': 'threshold_hours is required',
                'code': 'MISSING_THRESHOLD'
            }), 400
        
        new_threshold = data['threshold_hours']
        
        # Validate type
        if not isinstance(new_threshold, int):
            return jsonify({
                'error': 'threshold_hours must be an integer',
                'code': 'INVALID_TYPE'
            }), 400
        
        # Validate range
        if new_threshold < MIN_THRESHOLD_HOURS:
            return jsonify({
                'error': f'threshold_hours must be at least {MIN_THRESHOLD_HOURS}',
                'code': 'THRESHOLD_TOO_LOW'
            }), 400
        
        if new_threshold > MAX_THRESHOLD_HOURS:
            return jsonify({
                'error': f'threshold_hours must be at most {MAX_THRESHOLD_HOURS}',
                'code': 'THRESHOLD_TOO_HIGH'
            }), 400
        
        # Update the global config
        import config.deletion_config as config
        config.ACCOUNT_DELETION_THRESHOLD_HOURS = new_threshold
        
        # Validate and log warning if needed
        validate_threshold()
        
        return jsonify({
            'message': 'Deletion threshold updated successfully',
            'threshold_hours': new_threshold
        }), 200
        
    except Exception as e:
        return jsonify({'error': str(e), 'code': 'SERVER_ERROR'}), 500

@admin_api.route('/admin/deletion-queue/trigger', methods=['POST'])
@admin_required
def trigger_deletion_queue():
    """
    Manually trigger the deletion scheduler to process the queue immediately.
    Returns stats about the run.
    """
    try:
        # Trigger the deletion process
        result = trigger_deletion_manually()
        
        # Get updated queue stats
        Query_ = Query()
        marked_users = users_db.search(Query_.marked_for_deletion == True)
        
        # Count users that were just processed (this is simplified)
        processed = result.get('queued_users', 0)
        
        # In a real implementation, you'd return actual stats from the deletion run
        # For now, we'll return simplified stats
        return jsonify({
            'message': 'Deletion scheduler triggered',
            'processed': processed,
            'deleted': 0,  # TODO: Track this in the deletion function
            'failed': 0   # TODO: Track this in the deletion function
        }), 200
        
    except Exception as e:
        return jsonify({'error': str(e), 'code': 'SERVER_ERROR'}), 500


# ---------------------------------------------------------------------------
# Test-only endpoint — active ONLY when DB_ENV=e2e
# ---------------------------------------------------------------------------

@admin_api.route('/admin/test/digest-token', methods=['POST'])
def create_test_digest_token():
    """Create a valid DigestActionToken for E2E tests.

    Only active when DB_ENV=e2e. Requires authentication.
    """
    if os.environ.get('DB_ENV') != 'e2e':
        return jsonify({'error': 'Not found', 'code': 'NOT_FOUND'}), 404

    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': 'UNAUTHORIZED'}), 401

    data = request.get_json() or {}
    child_id = data.get('child_id')
    entity_id = data.get('entity_id')
    entity_type = data.get('entity_type')
    action = data.get('action')
    expires_in_hours = data.get('expires_in_hours', 24)

    if not all([child_id, entity_id, entity_type, action]):
        return jsonify({'error': 'child_id, entity_id, entity_type, and action are required',
                        'code': 'MISSING_FIELDS'}), 400

    if entity_type not in ('chore', 'reward'):
        return jsonify({'error': 'entity_type must be "chore" or "reward"',
                        'code': 'INVALID_ENTITY_TYPE'}), 400

    if action not in ('approve', 'deny'):
        return jsonify({'error': 'action must be "approve" or "deny"',
                        'code': 'INVALID_ACTION'}), 400

    try:
        from utils.digest_token import create_action_token
        token = create_action_token(
            user_id=user_id,
            child_id=child_id,
            entity_id=entity_id,
            entity_type=entity_type,
            action=action,
            expiry_hours=int(expires_in_hours),
        )
        return jsonify({'token': token.id}), 200
    except Exception as e:
        return jsonify({'error': str(e), 'code': 'SERVER_ERROR'}), 500


@admin_api.route('/admin/test/send-digest', methods=['POST'])
def send_test_digest():
    """Trigger a digest email for a specific user by email address.

    Only active when DB_ENV is not 'production'. Requires admin authentication.
    Note: actual email delivery is skipped in e2e mode by email_sender.
    """
    if os.environ.get('DB_ENV') == 'production':
        return jsonify({'error': 'Not found', 'code': 'NOT_FOUND'}), 404

    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': 'UNAUTHORIZED'}), 401

    # Verify caller is admin
    caller_dict = users_db.get(Query().id == user_id)
    if not caller_dict or caller_dict.get('role') != 'admin':
        return jsonify({'error': 'Admin access required', 'code': 'ADMIN_REQUIRED'}), 403

    data = request.get_json() or {}
    email = data.get('email', '').strip().lower()
    if not email:
        return jsonify({'error': 'email is required', 'code': 'MISSING_FIELDS'}), 400

    target = users_db.get(Query().email == email)
    if not target:
        return jsonify({'error': 'User not found', 'code': 'USER_NOT_FOUND'}), 404

    target_id = target.get('id')
    target_email = target.get('email')

    try:
        from flask import current_app
        from utils.digest_scheduler import send_digest_for_user
        frontend_url = current_app.config.get('FRONTEND_URL', 'https://localhost:5173')
        items_sent = send_digest_for_user(target_id, target_email, frontend_url)
        return jsonify({'items_sent': items_sent}), 200
    except Exception as e:
        return jsonify({'error': str(e), 'code': 'SERVER_ERROR'}), 500
