import os
import json

from src.extensions import db 
from datetime import datetime
from src.models.user import User
from werkzeug.utils import secure_filename
from src.models import Agente, AgenteTreino 
from src.models.agente import AgentUserShare
from src.services.agent_service import AgentService 
from flask_login import login_required, current_user
from src.discord.discord_webhook import send_discord_audit_log
from flask import Blueprint, request, jsonify, flash, redirect, url_for, render_template

agent_bp = Blueprint('agent', __name__, template_folder='../templates')

UPLOAD_FOLDER = 'uploads/agentes' 
ALLOWED_EXTENSIONS = {'txt', 'csv', 'xlsx', 'pdf'} 

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@agent_bp.route('/novo', methods=['GET', 'POST']) 
@login_required
def novo_agente(): 
    print("[DEBUG ROUTE] Rota /novo acessada.") 
    if request.method == 'POST':
        print("[DEBUG ROUTE] Método POST recebido.")
        nome = request.form.get('nome')
        descricao = request.form.get('descricao') 
        arquivos = request.files.getlist('arquivos')

        model_identifier = request.form.get('model_identifier')
        temperature_str = request.form.get('temperature', '70')
        max_tokens_str = request.form.get('max_tokens', '2048')
        top_p_str = request.form.get('top_p', '90')
        frequency_penalty_str = request.form.get('frequency_penalty', '0')
        system_prompt = request.form.get('system_prompt')
        examples_json_str = request.form.get('examples_json')
        welcome_message = request.form.get('welcome_message', 'Olá! Como posso te ajudar hoje?')

        if not nome:
            if request.is_json or 'application/json' in request.accept_mimetypes:
                return jsonify({'error': 'Nome do agente é obrigatório'}), 400
            flash('Nome do agente é obrigatório', 'danger')
            return render_template('agent/novo_agente.html')

        try:
            temperature = float(temperature_str) / 100.0
            max_tokens = int(max_tokens_str)
            top_p = float(top_p_str) / 100.0
            frequency_penalty = float(frequency_penalty_str) / 100.0
            
            agent_data = {
                'user_id': current_user.id,
                'nome': nome,
                'model_identifier': model_identifier,
                'descricao': descricao,
                'temperature': temperature,
                'max_tokens': max_tokens,
                'top_p': top_p,
                'frequency_penalty': frequency_penalty,
                'system_prompt': system_prompt,
                'examples_json': examples_json_str, 
                'welcome_message': welcome_message
            }

            print("[DEBUG ROUTE] Chamando AgentService.create_agent_with_training_files") 
            novo_agente_obj, error = AgentService.create_agent_with_training_files(agent_data, arquivos)
            print("[DEBUG ROUTE] AgentService.create_agent_with_training_files retornou.") 
        
            if error:
                print(f"[ERRO SERVICE] {error}")
                if request.is_json or 'application/json' in request.accept_mimetypes:
                    return jsonify({'error': error, 'success': False}), 500
                flash(f'Erro ao criar agente: {error}', 'danger')
                return render_template('agent/novo_agente.html')
        
            send_discord_audit_log(
                action="Criação de agente",
                user_id=current_user.email,
                object_type="Agente",
                object_id=novo_agente_obj.id,
                details=f"Agente criado: {novo_agente_obj.nome}",
                ip_address=request.remote_addr
            )
            if request.is_json or 'application/json' in request.accept_mimetypes:
                created_at = novo_agente_obj.created_at
                if not created_at:
                    created_at = datetime.utcnow()
                
                return jsonify({
                    'success': True,
                    'message': 'Agente criado com sucesso!',
                    'agent': {
                        'id': novo_agente_obj.id,
                        'nome': novo_agente_obj.nome,
                        'descricao': novo_agente_obj.descricao,
                        'created_at': created_at.isoformat() if created_at else None
                    },
                    'redirect_url': url_for('agent.list_agents_page_dinamica')
                }), 201 
            flash('Agente cadastrado com sucesso!', 'success')
            return redirect(url_for('agent.list_agents_page_dinamica')) 
            
        except Exception as e:
            db.session.rollback()
            error_message = f'Erro inesperado ao processar formulário: {str(e)}'
            print(f"[ERRO GERAL] {error_message}")
            
            if request.is_json or 'application/json' in request.accept_mimetypes:
                return jsonify({'error': error_message, 'success': False}), 500
            
            flash(error_message, 'danger')
            return render_template('agent/novo_agente.html') 
            
    return render_template('agent/novo_agente.html') 

@agent_bp.route('/lista') 
@login_required
def lista_agentes(): 
    agentes = db.session.query(Agente).filter_by(user_id=current_user.id).all()
    return render_template('agent/lista_agentes.html', agentes=agentes, current_agent=agentes[0] if agentes else None)

@agent_bp.route('/editar/<int:agente_id>', methods=['GET', 'POST']) 
@login_required
def editar_agente(agente_id): 
    if hasattr(current_user, 'role') and current_user.role == 'superadmin':
        agente = db.session.query(Agente).filter_by(id=agente_id).first_or_404()
    else:
        agente = db.session.query(Agente).filter_by(id=agente_id, user_id=current_user.id).first_or_404()

    if request.method == 'POST':
        agente.nome = request.form.get('nome', agente.nome)
        agente.descricao = request.form.get('descricao', agente.descricao)
        agente.model_identifier = request.form.get('model_identifier', agente.model_identifier)
        try:
            agente.temperature = float(request.form.get('temperature', agente.temperature * 100)) / 100.0
        except Exception:
            pass
        try:
            agente.max_tokens = int(request.form.get('max_tokens', agente.max_tokens))
        except Exception:
            pass
        try:
            agente.top_p = float(request.form.get('top_p', agente.top_p * 100)) / 100.0
        except Exception:
            pass
        try:
            agente.frequency_penalty = float(request.form.get('frequency_penalty', agente.frequency_penalty * 100)) / 100.0
        except Exception:
            pass
        agente.system_prompt = request.form.get('system_prompt', agente.system_prompt)
        
        agente.welcome_message = request.form.get('welcome_message', agente.welcome_message or 'Olá! Como posso te ajudar hoje?')
        
        examples_json = request.form.get('examples_json')
        print(f"[DEBUG] Valor recebido de examples_json: {examples_json}")
        if examples_json:
            agente.example_prompt = examples_json
        else:
            example_prompt_fallback = request.form.get('example_prompt')
            if example_prompt_fallback:
                agente.example_prompt = example_prompt_fallback
            else:
                agente.example_prompt = '||'.join(request.form.getlist('example_prompt'))
        
        arquivos = request.files.getlist('arquivos')
        agent_upload_folder = os.path.join(UPLOAD_FOLDER, str(agente.id))
        os.makedirs(agent_upload_folder, exist_ok=True)

        for arquivo in arquivos:
            if arquivo and arquivo.filename and allowed_file(arquivo.filename):
                filename = secure_filename(arquivo.filename)
                caminho = os.path.join(agent_upload_folder, filename)
                arquivo.save(caminho)
                existe_treino = db.session.query(AgenteTreino).filter_by(agente_id=agente.id, arquivo=filename).first()
                if not existe_treino:
                    treino = AgenteTreino(agente_id=agente.id, arquivo=filename)
                    db.session.add(treino)
        try:
            print(f"[DEBUG] Valor de example_prompt antes do commit: {agente.example_prompt}")
            db.session.commit()
            send_discord_audit_log(
                action="Edição de agente",
                user_id=current_user.id,
                object_type="Agente",
                object_id=agente.id,
                details=f"Agente editado: {agente.nome}",
                ip_address=request.remote_addr
            )
            if request.is_json or 'application/json' in request.accept_mimetypes:
                return jsonify({
                    'success': True,
                    'message': 'Agente atualizado com sucesso!',
                    'redirect_url': url_for('agent.list_agents_page_dinamica')
                })
            flash('Agente atualizado com sucesso!', 'success')
        except Exception as e:
            db.session.rollback()
            if request.is_json or 'application/json' in request.accept_mimetypes:
                return jsonify({'success': False, 'error': str(e)}), 500
            flash(f'Erro ao atualizar agente: {str(e)}', 'danger')
        return redirect(url_for('agent.list_agents_page_dinamica')) 
    
    examples_list = []
    if agente.example_prompt:
        try:
            examples_list = json.loads(agente.example_prompt)
        except Exception:
            examples_list = []
    return render_template('agent/editar_agente.html', agente=agente, current_agent=agente, examples_list=examples_list)

@agent_bp.route('/delete/<int:agente_id>', methods=['POST']) 
@login_required
def delete_agente(agente_id):
    success, error = AgentService.delete_agent(agente_id) 
    
    if request.is_json or 'application/json' in request.accept_mimetypes:
        if success:
            send_discord_audit_log(
                action="Exclusão de agente",
                user_id=current_user.id,
                object_type="Agente",
                object_id=agente_id,
                details="Agente excluído com sucesso",
                ip_address=request.remote_addr
            )
            return jsonify({'success': True, 'message': 'Agente excluído com sucesso.'})
        else:
            return jsonify({'success': False, 'error': error or 'Erro ao excluir agente.'}), 400

    if success:
        send_discord_audit_log(
            action="Exclusão de agente",
            user_id=current_user.id,
            object_type="Agente",
            object_id=agente_id,
            details="Agente excluído com sucesso",
            ip_address=request.remote_addr
        )
        flash('Agente excluído com sucesso!', 'success')
    else:
        flash(error or 'Erro ao excluir agente.', 'danger')
    return redirect(url_for('agent.list_agents_page_dinamica')) 


@agent_bp.route('/agents')
@login_required
def list_agents_page_dinamica(): 
    return render_template('agents.html') 

@agent_bp.route('/api/agents', methods=['GET'])
@login_required
def api_get_user_agents_dinamicos(): 
    """
    Endpoint da API para buscar a lista de agentes do usuário logado com estatísticas,
    usado pelo JavaScript em agents.html.
    """
    agents_data, error = AgentService.get_user_agents_with_stats()

    if error:
        print(f"API Error em /api/agents: {error}")
        return jsonify({"error": "Falha ao buscar lista de agentes.", "details": error}), 500
    
    return jsonify(agents_data)

@agent_bp.route('/api/agent/<int:agent_id>/welcome', methods=['GET'])
@login_required
def get_agent_welcome_message(agent_id):
    """Retorna a mensagem de boas-vindas de um agente específico"""
    try:
        print(f"[DEBUG] API welcome chamada para agente {agent_id} por usuário {current_user.id}")
        agente = db.session.get(Agente, agent_id)
        
        if not agente:
            print(f"[DEBUG] Agente {agent_id} não encontrado")
            return jsonify({'error': 'Agente não encontrado'}), 404
        
        print(f"[DEBUG] Agente encontrado: {agente.nome}")
        print(f"[DEBUG] Welcome message: {repr(agente.welcome_message)}")
        
        return jsonify({
            'agent_id': agente.id,
            'agent_name': agente.nome,
            'welcome_message': agente.welcome_message
        })
        
    except Exception as e:
        print(f"[ERROR] Erro ao buscar mensagem de boas-vindas do agente {agent_id}: {str(e)}")
        return jsonify({'error': 'Erro interno do servidor'}), 500

@agent_bp.route('/agent/<int:agent_id>/chat') 
@login_required
def start_agent_chat_route(agent_id):
    agente = db.session.get(Agente, agent_id)
    if not agente or (hasattr(agente, 'user_id') and agente.user_id != current_user.id and getattr(current_user, 'role', '') != 'superadmin'):
        flash("Agente não encontrado ou acesso negado.", "danger")
        return redirect(url_for('agent.list_agents_page_dinamica'))
    return redirect(url_for('chat.chat_redirect', agent_id=agent_id))

@agent_bp.route('/agente/<int:agent_id>/compartilhar', methods=['POST'])
@login_required
def compartilhar_agente(agent_id):
    data = request.get_json()
    user_email = data.get('email')
    permission = data.get('permission', 'view')
    user = User.query.filter_by(email=user_email).first()
    if not user:
        return jsonify({'error': 'Usuário não encontrado'}), 404
    agente = Agente.query.get(agent_id)
    if not agente or agente.user_id != current_user.id:
        return jsonify({'error': 'Acesso negado'}), 403
    existing = AgentUserShare.query.filter_by(agent_id=agent_id, user_id=user.id).first()
    if existing:
        return jsonify({'message': 'Já compartilhado'}), 200
    share = AgentUserShare(agent_id=agent_id, user_id=user.id, permission=permission)
    db.session.add(share)
    db.session.commit()
    send_discord_audit_log(
        action="Compartilhamento de agente",
        user_id=current_user.id,
        object_type="Agente",
        object_id=agent_id,
        details=f"Agente {agente.nome} compartilhado com {user.email} (perm: {permission})",
        ip_address=request.remote_addr
    )
    return jsonify({'message': 'Agente compartilhado com sucesso'}), 201

@agent_bp.route('/agente/<int:agent_id>/compartilhar/<int:user_id>', methods=['DELETE'])
@login_required
def descompartilhar_agente(agent_id, user_id):
    agente = Agente.query.get(agent_id)
    if not agente or agente.user_id != current_user.id:
        return jsonify({'error': 'Acesso negado'}), 403
    share = AgentUserShare.query.filter_by(agent_id=agent_id, user_id=user_id).first()
    if not share:
        return jsonify({'error': 'Compartilhamento não encontrado'}), 404
    db.session.delete(share)
    db.session.commit()
    send_discord_audit_log(
        action="Descompartilhamento de agente",
        user_id=current_user.id,
        object_type="Agente",
        object_id=agent_id,
        details=f"Agente {agente.nome} descompartilhado de {share.user_id}",
        ip_address=request.remote_addr
    )
    return jsonify({'message': 'Compartilhamento removido'}), 200

@agent_bp.route('/agentes/compartilhados', methods=['GET'])
@login_required
def listar_agentes_compartilhados():
    shares = AgentUserShare.query.filter_by(user_id=current_user.id).all()
    agentes = []
    for share in shares:
        agente = Agente.query.get(share.agent_id)
        if agente:
            agentes.append(agente.to_dict())
    return jsonify({'agentes': agentes})

@agent_bp.route('/api/users/search')
@login_required
def search_users():
    q = request.args.get('q', '').strip().lower()
    if not q or len(q) < 3:
        return jsonify([])
    users = User.query.filter((User.email.ilike(f'%{q}%')) | (User.username.ilike(f'%{q}%'))).limit(10).all()
    results = [
        {'id': u.id, 'email': u.email, 'username': u.username}
        for u in users if u.id != current_user.id
    ]
    return jsonify(results)

@agent_bp.route('/admin/create_user', methods=['GET', 'POST'])
@login_required
def admin_create_user():
    if not hasattr(current_user, 'role') or current_user.role != 'superadmin':
        return render_template('error.html', error='Acesso negado'), 403
    if request.method == 'POST':
        username = request.form.get('username')
        email = request.form.get('email')
        password = request.form.get('password')
        if not username or not email or not password:
            return render_template('admin/create_user.html', error='Todos os campos são obrigatórios')
        if User.query.filter_by(username=username).first() or User.query.filter_by(email=email).first():
            return render_template('admin/create_user.html', error='Usuário ou e-mail já existe')
        user = User(username=username, email=email)
        user.set_password(password)
        db.session.add(user)
        db.session.commit()
        send_discord_audit_log(
            action="Criação de usuário admin",
            user_id=current_user.id,
            object_type="Usuário",
            object_id=user.id,
            details=f"Usuário admin criado: {username} ({email})",
            ip_address=request.remote_addr
        )
        return render_template('admin/create_user.html', success='Usuário criado com sucesso!')
    return render_template('admin/create_user.html')

@agent_bp.route('/api/agents/<public_token>/copied', methods=['POST'])
def notify_public_token_copied(public_token):
    from src.models import Agente
    from src.discord.discord_webhook import send_discord_audit_log
    import datetime
    agente = Agente.query.filter_by(public_token=public_token).first()
    if not agente:
        return {'error': 'Token não encontrado'}, 404
    send_discord_audit_log(
        action="Token de agente copiado",
        user_id=None,
        object_type="Agente",
        object_id=agente.id,
        details=f"Token copiado: {public_token} | IP: {request.remote_addr} | Horário: {datetime.datetime.utcnow().isoformat()} ",
        ip_address=request.remote_addr
    )
    return {'success': True}