from flask import Blueprint, request, render_template, redirect, url_for, flash, jsonify
from functions.database import get_db_connection, Militante, EmailMilitante, Endereco, Celula, Setor, ComiteRegional
from functions.decorators import require_login
from functions.validations import validar_cpf
from functions.rbac import Permission
from utils.date_utils import validar_data, converter_data, calcular_idade
from datetime import datetime
from sqlalchemy.orm import joinedload
from flask_login import current_user

militante_bp = Blueprint('militante', __name__)

@militante_bp.route("/militantes/criar", methods=["POST"])
@require_login
def criar():
    """Cria um novo militante"""
    try:
        data = request.get_json()
        
        # Validações básicas
        if not data.get('nome') or not data.get('cpf'):
            return jsonify({
                'status': 'error',
                'message': 'Nome e CPF são obrigatórios'
            }), 400
        
        if not validar_cpf(data['cpf']):
            return jsonify({
                'status': 'error',
                'message': 'CPF inválido'
            }), 400
        
        db = get_db_connection()
        
        # Verificar se CPF já existe
        if db.query(Militante).filter_by(cpf=data['cpf']).first():
            return jsonify({
                'status': 'error',
                'message': 'CPF já cadastrado'
            }), 400
        
        # Criar endereço se fornecido
        endereco_id = None
        if data.get('endereco'):
            endereco = Endereco(**data['endereco'])
            db.add(endereco)
            db.flush()
            endereco_id = endereco.id
        
        # Criar militante
        militante = Militante(
            nome=data['nome'],
            cpf=data['cpf'],
            titulo_eleitoral=data.get('titulo_eleitoral'),
            data_nascimento=converter_data(data.get('data_nascimento')) if data.get('data_nascimento') else None,
            data_entrada_oci=converter_data(data.get('data_entrada_oci')) if data.get('data_entrada_oci') else None,
            data_efetivacao_oci=converter_data(data.get('data_efetivacao_oci')) if data.get('data_efetivacao_oci') else None,
            telefone1=data.get('telefone1'),
            telefone2=data.get('telefone2'),
            profissao=data.get('profissao'),
            regime_trabalho=data.get('regime_trabalho'),
            empresa=data.get('empresa'),
            contratante=data.get('contratante'),
            instituicao_ensino=data.get('instituicao_ensino'),
            tipo_instituicao=data.get('tipo_instituicao'),
            sindicato=data.get('sindicato'),
            cargo_sindical=data.get('cargo_sindical'),
            dirigente_sindical=data.get('dirigente_sindical', False),
            central_sindical=data.get('central_sindical'),
            endereco_id=endereco_id,
            celula_id=data.get('celula_id'),
            registrado_por=current_user.id
        )
        
        db.add(militante)
        db.flush()
        
        # Criar email se fornecido
        if data.get('email'):
            email = EmailMilitante(
                militante_id=militante.id,
                endereco_email=data['email']
            )
            db.add(email)
        
        db.commit()
        
        return jsonify({
            'status': 'success',
            'message': 'Militante criado com sucesso',
            'militante_id': militante.id
        })
        
    except Exception as e:
        db.rollback()
        return jsonify({
            'status': 'error',
            'message': f'Erro ao criar militante: {str(e)}'
        }), 500
    finally:
        db.close()

@militante_bp.route("/militantes")
@require_login
def listar():
    """Lista todos os militantes com controle de permissões no nível de dados"""
    db = get_db_connection()
    try:
        # SEMPRE renderizar o template, mas filtrar os dados baseado nas permissões
        militantes = []
        
        # Verificar permissões para filtrar dados
        if current_user.is_admin:
            # Admin vê todos
            militantes = db.query(Militante).options(
                joinedload(Militante.emails),
                joinedload(Militante.endereco),
                joinedload(Militante.celula)
            ).order_by(Militante.nome).all()
        elif hasattr(current_user, 'has_permission'):
            if current_user.has_permission(Permission.VIEW_CC_REPORTS):
                # CC vê todos
                militantes = db.query(Militante).options(
                    joinedload(Militante.emails),
                    joinedload(Militante.endereco),
                    joinedload(Militante.celula)
                ).order_by(Militante.nome).all()
            elif current_user.has_permission(Permission.VIEW_CR_REPORTS):
                # CR vê do seu CR
                if hasattr(current_user, 'cr_id') and current_user.cr_id:
                    militantes = db.query(Militante).join(Celula).join(Setor).filter(
                        Setor.cr_id == current_user.cr_id
                    ).options(
                        joinedload(Militante.emails),
                        joinedload(Militante.endereco),
                        joinedload(Militante.celula)
                    ).order_by(Militante.nome).all()
            elif current_user.has_permission(Permission.VIEW_SECTOR_REPORTS):
                # Setor vê do seu setor
                if hasattr(current_user, 'setor_id') and current_user.setor_id:
                    militantes = db.query(Militante).join(Celula).filter(
                        Celula.setor_id == current_user.setor_id
                    ).options(
                        joinedload(Militante.emails),
                        joinedload(Militante.endereco),
                        joinedload(Militante.celula)
                    ).order_by(Militante.nome).all()
            elif current_user.has_permission(Permission.VIEW_CELL_DATA):
                # Célula vê da sua célula
                if hasattr(current_user, 'celula_id') and current_user.celula_id:
                    militantes = db.query(Militante).filter(
                        Militante.celula_id == current_user.celula_id
                    ).options(
                        joinedload(Militante.emails),
                        joinedload(Militante.endereco),
                        joinedload(Militante.celula)
                    ).order_by(Militante.nome).all()
        
        # Buscar dados auxiliares para o template
        celulas = db.query(Celula).all()
        setores = db.query(Setor).all()
        
        # SEMPRE renderizar o template, independente das permissões
        # O controle é feito no nível dos dados, não do template
        return render_template('listar_militantes.html', 
                             militantes=militantes, 
                             Militante=Militante,
                             celulas=celulas,
                             setores=setores)
    except Exception as e:
        print(f"Erro no controller de militantes: {e}")
        # Em caso de erro, renderizar com dados vazios
        return render_template('listar_militantes.html', 
                             militantes=[], 
                             Militante=Militante,
                             celulas=[],
                             setores=[])
    finally:
        db.close()

@militante_bp.route("/militantes/excluir/<int:id>", methods=["POST"])
@require_login
def excluir(id):
    """Exclui um militante"""
    db = get_db_connection()
    try:
        militante = db.query(Militante).get(id)
        if not militante:
            flash('Militante não encontrado.', 'danger')
            return redirect(url_for('militante.listar'))
        
        # Verificar permissões
        if not current_user.has_permission('gerenciar_militantes'):
            flash('Você não tem permissão para excluir militantes.', 'danger')
            return redirect(url_for('militante.listar'))
        
        db.delete(militante)
        db.commit()
        flash('Militante excluído com sucesso!', 'success')
        
    except Exception as e:
        db.rollback()
        flash('Erro ao excluir militante.', 'danger')
        print(f"Erro ao excluir militante: {e}")
    finally:
        db.close()
    
    return redirect(url_for('militante.listar'))

@militante_bp.route('/militantes/editar/<int:militante_id>', methods=['POST'])
@require_login
def editar(militante_id):
    """Edita um militante existente"""
    try:
        data = request.get_json()
        
        db = get_db_connection()
        militante = db.query(Militante).get(militante_id)
        
        if not militante:
            return jsonify({
                'status': 'error',
                'message': 'Militante não encontrado'
            }), 404
        
        # Atualizar dados básicos
        militante.nome = data.get('nome', militante.nome)
        militante.cpf = data.get('cpf', militante.cpf)
        militante.titulo_eleitoral = data.get('titulo_eleitoral', militante.titulo_eleitoral)
        militante.telefone1 = data.get('telefone1', militante.telefone1)
        militante.telefone2 = data.get('telefone2', militante.telefone2)
        militante.profissao = data.get('profissao', militante.profissao)
        militante.regime_trabalho = data.get('regime_trabalho', militante.regime_trabalho)
        militante.empresa = data.get('empresa', militante.empresa)
        militante.contratante = data.get('contratante', militante.contratante)
        militante.instituicao_ensino = data.get('instituicao_ensino', militante.instituicao_ensino)
        militante.tipo_instituicao = data.get('tipo_instituicao', militante.tipo_instituicao)
        militante.sindicato = data.get('sindicato', militante.sindicato)
        militante.cargo_sindical = data.get('cargo_sindical', militante.cargo_sindical)
        militante.dirigente_sindical = data.get('dirigente_sindical', militante.dirigente_sindical)
        militante.central_sindical = data.get('central_sindical', militante.central_sindical)
        
        # Atualizar datas
        if data.get('data_nascimento'):
            militante.data_nascimento = converter_data(data['data_nascimento'])
        if data.get('data_entrada_oci'):
            militante.data_entrada_oci = converter_data(data['data_entrada_oci'])
        if data.get('data_efetivacao_oci'):
            militante.data_efetivacao_oci = converter_data(data['data_efetivacao_oci'])
        
        # Atualizar endereço
        if data.get('endereco') and militante.endereco:
            endereco = militante.endereco
            endereco.cep = data['endereco'].get('cep', endereco.cep)
            endereco.estado = data['endereco'].get('estado', endereco.estado)
            endereco.cidade = data['endereco'].get('cidade', endereco.cidade)
            endereco.bairro = data['endereco'].get('bairro', endereco.bairro)
            endereco.rua = data['endereco'].get('rua', endereco.rua)
            endereco.numero = data['endereco'].get('numero', endereco.numero)
            endereco.complemento = data['endereco'].get('complemento', endereco.complemento)
        
        # Atualizar email
        if data.get('email') and militante.emails:
            militante.emails[0].endereco_email = data['email']
        
        db.commit()
        
        return jsonify({
            'status': 'success',
            'message': 'Militante atualizado com sucesso'
        })
        
    except Exception as e:
        db.rollback()
        return jsonify({
            'status': 'error',
            'message': f'Erro ao atualizar militante: {str(e)}'
        }), 500
    finally:
        db.close()

@militante_bp.route("/militantes/dados/<int:militante_id>")
@require_login
def buscar_dados(militante_id):
    """Busca os dados de um militante específico"""
    db = get_db_connection()
    try:
        militante = db.query(Militante).options(
            joinedload(Militante.emails),
            joinedload(Militante.endereco)
        ).get(militante_id)
        
        if not militante:
            return jsonify({
                'status': 'error',
                'message': 'Militante não encontrado'
            }), 404
        
        # Função auxiliar para formatar data com validação
        def formatar_data_segura(data):
            try:
                if not data:
                    return None
                return data.strftime('%Y-%m-%d')
            except Exception as e:
                print(f"Erro ao formatar data: {str(e)}, valor: {data}")
                return None
        
        # Preparar dados para retorno
        dados = {
            'id': militante.id,
            'nome': militante.nome,
            'cpf': militante.cpf,
            'titulo_eleitoral': militante.titulo_eleitoral,
            'data_nascimento': formatar_data_segura(militante.data_nascimento),
            'data_entrada_oci': formatar_data_segura(militante.data_entrada_oci),
            'data_efetivacao_oci': formatar_data_segura(militante.data_efetivacao_oci),
            'telefone1': militante.telefone1,
            'telefone2': militante.telefone2,
            'profissao': militante.profissao,
            'regime_trabalho': militante.regime_trabalho,
            'empresa': militante.empresa,
            'contratante': militante.contratante,
            'instituicao_ensino': militante.instituicao_ensino,
            'tipo_instituicao': militante.tipo_instituicao,
            'sindicato': militante.sindicato,
            'cargo_sindical': militante.cargo_sindical,
            'dirigente_sindical': militante.dirigente_sindical,
            'central_sindical': militante.central_sindical,
            'responsabilidades': militante.responsabilidades,
            'estado': militante.estado.value if militante.estado else None,
            'celula_id': militante.celula_id,
            'email': militante.emails[0].endereco_email if militante.emails else None,
            'endereco': {
                'cep': militante.endereco.cep if militante.endereco else None,
                'estado': militante.endereco.estado if militante.endereco else None,
                'cidade': militante.endereco.cidade if militante.endereco else None,
                'bairro': militante.endereco.bairro if militante.endereco else None,
                'rua': militante.endereco.rua if militante.endereco else None,
                'numero': militante.endereco.numero if militante.endereco else None,
                'complemento': militante.endereco.complemento if militante.endereco else None
            } if militante.endereco else None
        }
        
        return jsonify({
            'status': 'success',
            'data': dados
        })
        
    except Exception as e:
        return jsonify({
            'status': 'error',
            'message': f'Erro ao buscar dados: {str(e)}'
        }), 500
    finally:
        db.close()

@militante_bp.route("/api/setores/<int:cr_id>")
@require_login
def get_setores(cr_id):
    """Retorna setores de um CR específico"""
    db = get_db_connection()
    try:
        setores = db.query(Setor).filter_by(cr_id=cr_id).all()
        return jsonify([{'id': s.id, 'nome': s.nome} for s in setores])
    finally:
        db.close() 