from flask import Blueprint, jsonify, request, current_app
from functools import wraps
from models import (
    KeyValueSettings, User, Room, Conversation, RoomFile,
    SiteSettings, DocuPulseSettings, Event, Mail, ManagementAPIKey
)
from extensions import db
from datetime import datetime, timedelta
import os
import jwt
from werkzeug.security import generate_password_hash
import secrets

admin_api = Blueprint('admin_api', __name__)

def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = None
        if 'Authorization' in request.headers:
            token = request.headers['Authorization'].split(" ")[1]
        
        if not token:
            return jsonify({'message': 'Token is missing!'}), 401
        
        try:
            data = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=["HS256"])
            # Check if it's a management tool token
            if data.get('is_management'):
                return f(None, *args, **kwargs)  # Pass None as current_user for management tool
            
            current_user = User.query.get(data['user_id'])
            if not current_user or not current_user.is_admin:
                return jsonify({'message': 'Invalid token or insufficient permissions!'}), 401
        except:
            return jsonify({'message': 'Invalid token!'}), 401
        
        return f(current_user, *args, **kwargs)
    return decorated

def generate_management_api_key():
    """Generate a secure API key for the management tool"""
    return secrets.token_urlsafe(32)

def validate_management_api_key(api_key):
    """Validate if the provided API key is valid"""
    key = ManagementAPIKey.query.filter_by(api_key=api_key, is_active=True).first()
    if key:
        key.last_used_at = datetime.utcnow()
        db.session.commit()
        return True
    return False

@admin_api.route('/login', methods=['POST'])
def admin_login():
    data = request.get_json()
    if not data or 'email' not in data or 'password' not in data:
        return jsonify({'message': 'Email and password are required'}), 400
    user = User.query.filter_by(email=data['email']).first()
    if not user or not user.is_admin or not user.check_password(data['password']):
        return jsonify({'message': 'Invalid credentials or not an admin'}), 401
    token = jwt.encode({
        'user_id': user.id
    }, current_app.config['SECRET_KEY'], algorithm="HS256")
    return jsonify({'token': token})

@admin_api.route('/management-token', methods=['POST'])
def get_management_token():
    """Generate a JWT token for the management tool using API key authentication"""
    api_key = request.headers.get('X-API-Key')
    if not api_key or not validate_management_api_key(api_key):
        return jsonify({'message': 'Invalid API key'}), 401
    
    # Create a token without expiration
    token = jwt.encode({
        'user_id': 0,  # Special user ID for management tool
        'is_management': True
    }, current_app.config['SECRET_KEY'], algorithm="HS256")
    
    return jsonify({
        'token': token
    })

@admin_api.route('/management-api-key', methods=['POST'])
@token_required
def create_management_api_key(current_user):
    """Create a new API key for the management tool (only accessible by admin users)"""
    if not current_user.is_admin:
        return jsonify({'message': 'Insufficient permissions'}), 403
    
    data = request.get_json()
    if not data or 'name' not in data:
        return jsonify({'message': 'Name is required'}), 400
    
    api_key = generate_management_api_key()
    key = ManagementAPIKey(
        api_key=api_key,
        name=data['name'],
        created_by=current_user.id
    )
    db.session.add(key)
    db.session.commit()
    
    return jsonify({
        'api_key': api_key,
        'name': key.name,
        'created_at': key.created_at.isoformat(),
        'message': 'API key generated successfully. Store this key securely as it will not be shown again.'
    }), 201

@admin_api.route('/management-api-keys', methods=['GET'])
@token_required
def list_management_api_keys(current_user):
    """List all management API keys (only accessible by admin users)"""
    if not current_user.is_admin:
        return jsonify({'message': 'Insufficient permissions'}), 403
    
    keys = ManagementAPIKey.query.all()
    return jsonify([{
        'id': key.id,
        'name': key.name,
        'created_at': key.created_at.isoformat(),
        'last_used_at': key.last_used_at.isoformat() if key.last_used_at else None,
        'is_active': key.is_active,
        'created_by': key.created_by
    } for key in keys])

@admin_api.route('/management-api-key/<int:key_id>', methods=['DELETE'])
@token_required
def revoke_management_api_key(current_user, key_id):
    """Revoke a management API key (only accessible by admin users)"""
    if not current_user.is_admin:
        return jsonify({'message': 'Insufficient permissions'}), 403
    
    key = ManagementAPIKey.query.get(key_id)
    if not key:
        return jsonify({'message': 'API key not found'}), 404
    
    key.is_active = False
    db.session.commit()
    return jsonify({'message': 'API key revoked successfully'})

# Key-Value Settings CRUD
@admin_api.route('/key-value', methods=['GET'])
@token_required
def get_key_values(current_user):
    settings = KeyValueSettings.query.all()
    return jsonify([{'key': s.key, 'value': s.value} for s in settings])

@admin_api.route('/key-value/<key>', methods=['GET'])
@token_required
def get_key_value(current_user, key):
    setting = KeyValueSettings.query.filter_by(key=key).first()
    if not setting:
        return jsonify({'message': 'Key not found'}), 404
    return jsonify({'key': setting.key, 'value': setting.value})

@admin_api.route('/key-value', methods=['POST'])
@token_required
def create_key_value(current_user):
    data = request.get_json()
    if not data or 'key' not in data or 'value' not in data:
        return jsonify({'message': 'Missing key or value'}), 400
    
    setting = KeyValueSettings(key=data['key'], value=data['value'])
    db.session.add(setting)
    db.session.commit()
    return jsonify({'message': 'Key-value pair created successfully'}), 201

@admin_api.route('/key-value/<key>', methods=['PUT'])
@token_required
def update_key_value(current_user, key):
    setting = KeyValueSettings.query.filter_by(key=key).first()
    if not setting:
        return jsonify({'message': 'Key not found'}), 404
    
    data = request.get_json()
    if not data or 'value' not in data:
        return jsonify({'message': 'Missing value'}), 400
    
    setting.value = data['value']
    db.session.commit()
    return jsonify({'message': 'Key-value pair updated successfully'})

@admin_api.route('/key-value/<key>', methods=['DELETE'])
@token_required
def delete_key_value(current_user, key):
    setting = KeyValueSettings.query.filter_by(key=key).first()
    if not setting:
        return jsonify({'message': 'Key not found'}), 404
    
    db.session.delete(setting)
    db.session.commit()
    return jsonify({'message': 'Key-value pair deleted successfully'})

# Contacts (Users) CRUD
@admin_api.route('/contacts', methods=['GET'])
@token_required
def get_contacts(current_user):
    users = User.query.all()
    return jsonify([{
        'id': user.id,
        'username': user.username,
        'email': user.email,
        'last_name': user.last_name,
        'phone': user.phone,
        'company': user.company,
        'position': user.position,
        'is_active': user.is_active,
        'created_at': user.created_at.isoformat()
    } for user in users])

@admin_api.route('/contacts/<int:user_id>', methods=['GET'])
@token_required
def get_contact(current_user, user_id):
    user = User.query.get(user_id)
    if not user:
        return jsonify({'message': 'User not found'}), 404
    return jsonify({
        'id': user.id,
        'username': user.username,
        'email': user.email,
        'last_name': user.last_name,
        'phone': user.phone,
        'company': user.company,
        'position': user.position,
        'is_active': user.is_active,
        'created_at': user.created_at.isoformat()
    })

@admin_api.route('/contacts', methods=['POST'])
@token_required
def create_contact(current_user):
    data = request.get_json()
    required_fields = ['username', 'email', 'last_name']
    if not all(field in data for field in required_fields):
        return jsonify({'message': 'Missing required fields'}), 400
    
    if User.query.filter_by(email=data['email']).first():
        return jsonify({'message': 'Email already exists'}), 400
    
    user = User(
        username=data['username'],
        email=data['email'],
        last_name=data['last_name'],
        phone=data.get('phone'),
        company=data.get('company'),
        position=data.get('position')
    )
    user.set_password(data.get('password', 'changeme'))
    
    db.session.add(user)
    db.session.commit()
    return jsonify({'message': 'Contact created successfully', 'id': user.id}), 201

@admin_api.route('/contacts/<int:user_id>', methods=['PUT'])
@token_required
def update_contact(current_user, user_id):
    user = User.query.get(user_id)
    if not user:
        return jsonify({'message': 'User not found'}), 404
    
    data = request.get_json()
    if 'email' in data and data['email'] != user.email:
        if User.query.filter_by(email=data['email']).first():
            return jsonify({'message': 'Email already exists'}), 400
        user.email = data['email']
    
    user.username = data.get('username', user.username)
    user.last_name = data.get('last_name', user.last_name)
    user.phone = data.get('phone', user.phone)
    user.company = data.get('company', user.company)
    user.position = data.get('position', user.position)
    user.is_active = data.get('is_active', user.is_active)
    
    if 'password' in data:
        user.set_password(data['password'])
    
    db.session.commit()
    return jsonify({'message': 'Contact updated successfully'})

@admin_api.route('/contacts/<int:user_id>', methods=['DELETE'])
@token_required
def delete_contact(current_user, user_id):
    user = User.query.get(user_id)
    if not user:
        return jsonify({'message': 'User not found'}), 404
    
    db.session.delete(user)
    db.session.commit()
    return jsonify({'message': 'Contact deleted successfully'})

# Statistics
@admin_api.route('/statistics', methods=['GET'])
@token_required
def get_statistics(current_user):
    room_count = Room.query.count()
    conversation_count = Conversation.query.count()
    
    # Calculate total storage
    total_storage = 0
    for file in RoomFile.query.all():
        if file.size:
            total_storage += file.size
    
    return jsonify({
        'rooms': room_count,
        'conversations': conversation_count,
        'total_storage': total_storage
    })

# Website Settings CRUD
@admin_api.route('/settings', methods=['GET'])
@token_required
def get_settings(current_user):
    settings = SiteSettings.get_settings()
    return jsonify({
        'primary_color': settings.primary_color,
        'secondary_color': settings.secondary_color,
        'company_name': settings.company_name,
        'company_logo': settings.company_logo,
        'company_website': settings.company_website,
        'company_email': settings.company_email,
        'company_phone': settings.company_phone,
        'company_address': settings.company_address,
        'company_city': settings.company_city,
        'company_state': settings.company_state,
        'company_zip': settings.company_zip,
        'company_country': settings.company_country,
        'company_description': settings.company_description,
        'company_industry': settings.company_industry
    })

@admin_api.route('/settings', methods=['PUT'])
@token_required
def update_settings(current_user):
    settings = SiteSettings.get_settings()
    data = request.get_json()
    
    for key, value in data.items():
        if hasattr(settings, key):
            setattr(settings, key, value)
    
    db.session.commit()
    return jsonify({'message': 'Settings updated successfully'})

# Website Logs
@admin_api.route('/logs', methods=['GET'])
@token_required
def get_logs(current_user):
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 50, type=int)
    
    events = Event.query.order_by(Event.timestamp.desc()).paginate(
        page=page, per_page=per_page, error_out=False
    )
    
    return jsonify({
        'events': [{
            'id': event.id,
            'event_type': event.event_type,
            'user_id': event.user_id,
            'timestamp': event.timestamp.isoformat(),
            'details': event.details,
            'ip_address': event.ip_address,
            'user_agent': event.user_agent
        } for event in events.items],
        'total': events.total,
        'pages': events.pages,
        'current_page': events.page
    })

# Mail Logs
@admin_api.route('/mail-logs', methods=['GET'])
@token_required
def get_mail_logs(current_user):
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 50, type=int)
    
    mails = Mail.query.order_by(Mail.created_at.desc()).paginate(
        page=page, per_page=per_page, error_out=False
    )
    
    return jsonify({
        'mails': [{
            'id': mail.id,
            'recipient': mail.recipient,
            'subject': mail.subject,
            'status': mail.status,
            'created_at': mail.created_at.isoformat(),
            'sent_at': mail.sent_at.isoformat() if mail.sent_at else None,
            'template_id': mail.template_id
        } for mail in mails.items],
        'total': mails.total,
        'pages': mails.pages,
        'current_page': mails.page
    })

# Resend Setup Mail
@admin_api.route('/resend-setup-mail/<int:user_id>', methods=['POST'])
@token_required
def resend_setup_mail(current_user, user_id):
    user = User.query.get(user_id)
    if not user:
        return jsonify({'message': 'User not found'}), 404
    
    # Generate a new password setup token
    token = PasswordSetupToken(
        user_id=user.id,
        token=generate_password_hash(str(user.id) + str(datetime.utcnow())),
        expires_at=datetime.utcnow() + timedelta(days=7)
    )
    db.session.add(token)
    
    # Create mail record
    mail = Mail(
        recipient=user.email,
        subject='DocuPulse Account Setup',
        body=f'Please click the following link to set up your account: {request.host_url}setup-password/{token.token}',
        status='pending'
    )
    db.session.add(mail)
    
    db.session.commit()
    return jsonify({'message': 'Setup mail queued for resending'}) 