from datetime import datetime
from flask import Blueprint, render_template, request, redirect, url_for, flash, session, jsonify
from ..models import db, Pessoa, Usuario, Campanha, MetaCadastrador, AuditoriaLog
from ..services.cep_service import consultar_cep
from ..utils.auth_decorators import login_required, write_required

cadastros_bp = Blueprint('cadastros', __name__, url_prefix='/cadastros')

BAIRROS_MANAUS = [
    'Alvorada', 'Adrianópolis', 'Aleixo', 'Armando Mendes', 'Betânia', 'Cachoeirinha', 
    'Centro', 'Cidade Nova', 'Compensa', 'Coroado', 'Crespo', 'Dom Pedro', 'Educandos', 
    'Flores', 'Glória', 'Japiim', 'Jorge Teixeira', 'Lago Azul', 'Lírio do Vale', 
    'Manoa', 'Monte das Oliveiras', 'Nova Cidade', 'Novo Aleixo', 'Novo Israel', 
    'Parque 10 de Novembro', 'Praça 14 de Janeiro', 'Redenção', 'Santa Etelvina', 
    'Santo Antônio', 'São Geraldo', 'São José Operário', 'São Raimundo', 'Tarumã', 
    'Vila da Prata', 'Zumbi dos Palmares'
]

ZONAS_MANAUS = {
    'Zona Norte': ['Cidade Nova', 'Lago Azul', 'Manoa', 'Monte das Oliveiras', 'Nova Cidade', 'Novo Israel', 'Santa Etelvina'],
    'Zona Leste': ['Armando Mendes', 'Coroado', 'Jorge Teixeira', 'Novo Aleixo', 'São José Operário', 'Zumbi dos Palmares'],
    'Zona Sul': ['Betânia', 'Cachoeirinha', 'Centro', 'Crespo', 'Educandos', 'Japiim', 'Praça 14 de Janeiro'],
    'Zona Oeste': ['Compensa', 'Glória', 'Lírio do Vale', 'Santo Antônio', 'São Raimundo', 'Tarumã', 'Vila da Prata'],
    'Centro-Sul': ['Adrianópolis', 'Aleixo', 'Flores', 'Parque 10 de Novembro', 'São Geraldo'],
    'Centro-Oeste': ['Alvorada', 'Dom Pedro', 'Redenção']
}

@cadastros_bp.route('/api/cep/<cep_num>')
@login_required
def api_consultar_cep(cep_num):
    """API de busca instantânea de CEP com resolução de Zona Urbana"""
    res = consultar_cep(cep_num)
    return jsonify(res)

def _build_multiplicador_tree(user_node, meta_default):
    nodes = []
    for sub in user_node.sub_cadastradores:
        m_lim = sub.meta_rel.meta if sub.meta_rel else meta_default
        total_dir = len(sub.cadastros)
        sub_tree = sub.total_sub_tree_cadastros()
        pct = min(round((total_dir / m_lim) * 100, 1), 100.0) if m_lim > 0 else 100
        nodes.append({
            'id': sub.id,
            'nome': sub.nome,
            'email': sub.email,
            'telefone': sub.telefone,
            'criado_em': sub.criado_em,
            'total_cadastros_diretos': total_dir,
            'total_sub_tree': sub_tree,
            'meta': m_lim,
            'percentual': pct,
            'meta_atingida': total_dir >= m_lim,
            'sub_nodes': _build_multiplicador_tree(sub, meta_default)
        })
    return nodes

def _contar_multiplicadores_sub_tree(user_node):
    count = len(user_node.sub_cadastradores)
    for sub in user_node.sub_cadastradores:
        count += _contar_multiplicadores_sub_tree(sub)
    return count

@cadastros_bp.route('/meus')
@login_required
def meus():
    """Painel do Multiplicador: métricas, cadastros e árvore da sub-rede de multiplicadores"""
    usuario_id = session.get('usuario_id')
    campanha_id = session.get('campanha_id')
    usuario = db.session.get(Usuario, usuario_id)
    campanha = db.session.get(Campanha, campanha_id) if campanha_id else None
    
    meus_cadastros = Pessoa.query.filter_by(cadastrador_id=usuario_id).order_by(Pessoa.criado_em.desc()).all()
    meta_obj = MetaCadastrador.query.filter_by(cadastrador_id=usuario_id).first()
    meta_default = campanha.meta_por_cadastrador if campanha else 25
    
    meta_limite = meta_obj.meta if meta_obj else meta_default
    total_realizado = len(meus_cadastros)
    total_sub_tree = usuario.total_sub_tree_cadastros() if usuario else total_realizado
    percentual = min(round((total_realizado / meta_limite) * 100, 1), 100.0) if meta_limite > 0 else 100
    
    # Métricas Apoiadores vs Multiplicadores
    total_apoiadores_diretos = sum(1 for p in meus_cadastros if not p.usuario_id)
    total_multiplicadores_diretos = len(usuario.sub_cadastradores) if usuario else 0
    total_multiplicadores_rede = _contar_multiplicadores_sub_tree(usuario) if usuario else 0
    
    # Árvore da sub-rede de multiplicadores
    arvore_sub_multiplicadores = _build_multiplicador_tree(usuario, meta_default) if usuario else []
    
    return render_template(
        'cadastros/meus.html',
        usuario=usuario,
        campanha=campanha,
        cadastros=meus_cadastros,
        total_realizado=total_realizado,
        total_sub_tree=total_sub_tree,
        meta_limite=meta_limite,
        percentual=percentual,
        total_apoiadores_diretos=total_apoiadores_diretos,
        total_multiplicadores_diretos=total_multiplicadores_diretos,
        total_multiplicadores_rede=total_multiplicadores_rede,
        arvore_sub_multiplicadores=arvore_sub_multiplicadores
    )

@cadastros_bp.route('/')
@login_required
def index():
    """Lista global de cadastros para Admin 1, Admin 2, Visualizador ou DEV"""
    campanha_id = session.get('campanha_id')
    user_role = session.get('usuario_perfil')
    
    query = Pessoa.query
    if user_role not in [Usuario.ROLE_DEV, Usuario.ROLE_ADMIN, Usuario.ROLE_VISUALIZADOR, 'admin_1', 'admin_2', 'superadmin_dev', 'administrador'] and campanha_id:
        query = query.filter_by(cadastrador_id=session.get('usuario_id'))
    elif campanha_id:
        query = query.filter_by(campanha_id=campanha_id)
        
    bairro_filtro = request.args.get('bairro')
    zona_filtro = request.args.get('zona')
    cadastrador_filtro = request.args.get('cadastrador_id')
    
    if bairro_filtro:
        query = query.filter_by(bairro=bairro_filtro)
    if zona_filtro:
        query = query.filter_by(zona=zona_filtro)
    if cadastrador_filtro:
        query = query.filter_by(cadastrador_id=int(cadastrador_filtro))
        
    cadastros = query.order_by(Pessoa.criado_em.desc()).all()
    cadastradores = Usuario.query.filter_by(campanha_id=campanha_id, perfil=Usuario.ROLE_CADASTRADOR).all() if campanha_id else []
    
    return render_template(
        'cadastros/lista.html',
        cadastros=cadastros,
        bairros=BAIRROS_MANAUS,
        zonas=list(ZONAS_MANAUS.keys()),
        cadastradores=cadastradores,
        bairro_filtro=bairro_filtro,
        zona_filtro=zona_filtro,
        cadastrador_filtro=cadastrador_filtro
    )

@cadastros_bp.route('/novo', methods=['GET', 'POST'])
@login_required
@write_required
def novo():
    """Formulário simplificado de cadastro com conversão atômica em Cadastrador (RN-CAD-04)"""
    usuario_id = session.get('usuario_id')
    usuario_logado = db.session.get(Usuario, usuario_id)
    campanha_id = session.get('campanha_id')
    campanha = db.session.get(Campanha, campanha_id) if campanha_id else None
    
    if request.method == 'POST':
        nome_completo = request.form.get('nome_completo', '').strip()
        cpf = request.form.get('cpf', '').strip()
        cpf_digits = ''.join(c for c in cpf if c.isdigit())
        
        telefone = request.form.get('telefone', '').strip()
        data_nascimento_str = request.form.get('data_nascimento')
        sexo = request.form.get('sexo', '')
        
        cep = request.form.get('cep', '').strip()
        rua = request.form.get('rua', '').strip()
        numero = request.form.get('numero', '').strip()
        complemento = request.form.get('complemento', '').strip()
        ponto_referencia = request.form.get('ponto_referencia', '').strip()
        bairro = request.form.get('bairro', 'Centro').strip()
        zona = request.form.get('zona', 'Zona Norte').strip()
        municipio = request.form.get('municipio', 'Manaus').strip()
        
        titulo_eleitor = request.form.get('titulo_eleitor', '').strip()
        zona_eleitoral = request.form.get('zona_eleitoral', '').strip()
        secao_eleitoral = request.form.get('secao_eleitoral', '').strip()
        
        observacao = request.form.get('observacao', '').strip()
        
        # RN-CAD-04: Participação na Rede (Sim, deseja se tornar Multiplicador)
        virar_cadastrador = request.form.get('virar_cadastrador') == 'on'
        email_cadastrador = request.form.get('email_cadastrador', '').strip()
        
        data_nascimento = None
        if data_nascimento_str:
            for fmt in ('%d/%m/%Y', '%Y-%m-%d'):
                try:
                    data_nascimento = datetime.strptime(data_nascimento_str.strip(), fmt).date()
                    break
                except ValueError:
                    pass
        
        if virar_cadastrador:
            if not cpf_digits and not cpf:
                flash('Para se tornar Multiplicador(a), informe o CPF.', 'danger')
                return render_template('cadastros/form.html', bairros=BAIRROS_MANAUS, zonas_dict=ZONAS_MANAUS, campanha=campanha)
                
            if Usuario.query.filter((Usuario.cpf == cpf_digits) | (Usuario.cpf == cpf)).first():
                flash('Este CPF já possui uma conta de Multiplicador no sistema.', 'danger')
                return render_template('cadastros/form.html', bairros=BAIRROS_MANAUS, zonas_dict=ZONAS_MANAUS, campanha=campanha)
                
            if email_cadastrador and Usuario.query.filter_by(email=email_cadastrador).first():
                flash('Este e-mail já possui uma conta no sistema.', 'danger')
                return render_template('cadastros/form.html', bairros=BAIRROS_MANAUS, zonas_dict=ZONAS_MANAUS, campanha=campanha)

        try:
            # Transação Atômica no Banco de Dados
            novo_usuario_id = None
            if virar_cadastrador:
                cpf_inicial = cpf_digits if cpf_digits else cpf
                novo_usuario = Usuario(
                    nome=nome_completo,
                    cpf=cpf_inicial,
                    email=email_cadastrador if email_cadastrador else None,
                    perfil=Usuario.ROLE_CADASTRADOR,
                    telefone=telefone,
                    primeiro_acesso=True,
                    campanha_id=campanha_id,
                    criado_por_id=usuario_id,
                    cadastrador_pai_id=usuario_id
                )
                # Senha inicial padrão é o CPF
                novo_usuario.set_senha(cpf_inicial)
                db.session.add(novo_usuario)
                db.session.flush()
                novo_usuario_id = novo_usuario.id
                
                # Meta para a nova conta
                meta_lim = campanha.meta_por_cadastrador if campanha else 25
                meta_nov = MetaCadastrador(
                    cadastrador_id=novo_usuario.id,
                    campanha_id=campanha_id or 1,
                    meta=meta_lim,
                    quantidade_atual=0
                )
                db.session.add(meta_nov)

            pessoa = Pessoa(
                nome_completo=nome_completo,
                cpf=cpf,
                telefone=telefone,
                data_nascimento=data_nascimento,
                sexo=sexo,
                cep=cep,
                rua=rua,
                numero=numero,
                complemento=complemento,
                ponto_referencia=ponto_referencia,
                bairro=bairro,
                zona=zona,
                municipio=municipio,
                titulo_eleitor=titulo_eleitor,
                zona_eleitoral=zona_eleitoral,
                secao_eleitoral=secao_eleitoral,
                observacao=observacao,
                cadastrador_id=usuario_id,
                campanha_id=campanha_id or 1,
                usuario_id=novo_usuario_id
            )
            db.session.add(pessoa)
            db.session.flush()
            
            # Atualiza meta do cadastrador logado
            meta_obj = MetaCadastrador.query.filter_by(cadastrador_id=usuario_id).first()
            if meta_obj:
                meta_obj.quantidade_atual += 1
            else:
                meta_lim = campanha.meta_por_cadastrador if campanha else 25
                meta_obj = MetaCadastrador(
                    cadastrador_id=usuario_id,
                    campanha_id=campanha_id or 1,
                    meta=meta_lim,
                    quantidade_atual=1
                )
                db.session.add(meta_obj)
                
            db.session.commit()

            detalhes_msg = f'Novo apoiador cadastrado: {pessoa.nome_completo}'
            if virar_cadastrador:
                detalhes_msg += ' (Convertido atômica em Cadastrador)'

            AuditoriaLog.registrar(
                usuario_id=usuario_id,
                usuario_nome=session.get('usuario_nome'),
                acao='CADASTRO_PESSOA_ATOMICO',
                entidade='Pessoa',
                entidade_id=pessoa.id,
                detalhes=detalhes_msg,
                ip=request.remote_addr
            )
            
            if virar_cadastrador:
                flash(f'Pessoa {nome_completo} cadastrada E convertida com sucesso em Cadastrador subordinado!', 'success')
            else:
                flash(f'Pessoa {nome_completo} cadastrada com sucesso!', 'success')
                
            if session.get('usuario_perfil') == Usuario.ROLE_CADASTRADOR:
                return redirect(url_for('cadastros.meus'))
            return redirect(url_for('cadastros.index'))

        except Exception as e:
            db.session.rollback()
            flash(f'Erro ao salvar cadastro na mesma transação: {e}', 'danger')
            return render_template('cadastros/form.html', bairros=BAIRROS_MANAUS, zonas_dict=ZONAS_MANAUS, campanha=campanha)
        
    return render_template(
        'cadastros/form.html',
        bairros=BAIRROS_MANAUS,
        zonas_dict=ZONAS_MANAUS,
        campanha=campanha
    )
