from datetime import datetime, timedelta
from functions.database import (
    Base, Militante, CotaMensal, TipoPagamento, Pagamento,
    MaterialVendido, TipoMaterial, VendaJornalAvulso, AssinaturaAnual,
    RelatorioCotasMensais, RelatorioVendasMateriais, engine, SessionLocal,
    Setor, ComiteCentral, Usuario, Role, EmailMilitante, Endereco
)
import random
from faker import Faker
import time

fake = Faker('pt_BR')

def criar_tipos_pagamento(session):
    """Cria tipos de pagamento padrão"""
    tipos = [
        "Dinheiro",
        "PIX",
        "Cartão de Crédito",
        "Cartão de Débito",
        "Transferência Bancária"
    ]
    for tipo in tipos:
        if not session.query(TipoPagamento).filter_by(descricao=tipo).first():
            session.add(TipoPagamento(descricao=tipo))
    session.commit()

def criar_tipos_material(session):
    """Cria tipos de material padrão"""
    tipos = [
        "Jornal",
        "Revista",
        "Livro",
        "Panfleto",
        "Cartilha"
    ]
    for tipo in tipos:
        if not session.query(TipoMaterial).filter_by(descricao=tipo).first():
            session.add(TipoMaterial(descricao=tipo))
    session.commit()

def criar_militantes(session, num_militantes):
    print(f"\nCriando {num_militantes} militantes...")
    militantes = []
    emails_usados = set()
    
    # Obter um setor existente
    setor = session.query(Setor).first()
    if not setor:
        print("Erro: Nenhum setor encontrado!")
        return []
    
    for i in range(num_militantes):
        try:
            nome = fake.name()
            cpf = fake.cpf()
            
            while True:
                email = fake.email()
                if email not in emails_usados:
                    emails_usados.add(email)
                    break
            
            endereco = Endereco(
                estado=fake.estado_sigla(),
                cidade=fake.city(),
                bairro=fake.bairro(),
                rua=fake.street_name(),
                numero=str(random.randint(1, 999)),
                complemento=f"Bloco {random.randint(1, 10)}, Apto {random.randint(1, 999)}" if random.random() < 0.3 else None,
                cep=fake.postcode()
            )
            session.add(endereco)
            session.flush()
            
            print(f"Criando militante {i+1}: {nome} (CPF: {cpf})")
            
            militante = Militante(
                nome=nome,
                cpf=cpf,
                titulo_eleitoral=str(random.randint(100000000000, 999999999999)),
                data_nascimento=fake.date_of_birth(minimum_age=18, maximum_age=65),
                data_entrada_oci=fake.date_between(start_date='-5y', end_date='today'),
                data_efetivacao_oci=fake.date_between(start_date='-4y', end_date='today'),
                telefone1=fake.phone_number(),
                telefone2=fake.phone_number() if random.random() < 0.3 else None,
                profissao=fake.job(),
                regime_trabalho=random.choice(['CLT', 'PJ', 'Estatutário', 'Autônomo']),
                empresa=fake.company(),
                contratante=fake.company() if random.random() < 0.2 else None,
                instituicao_ensino=fake.company() if random.random() < 0.4 else None,
                tipo_instituicao=random.choice(['Federal', 'Estadual', 'Municipal', 'Privada']) if random.random() < 0.4 else None,
                sindicato=fake.company() if random.random() < 0.6 else None,
                cargo_sindical=random.choice(['Diretor', 'Delegado', 'Conselheiro']) if random.random() < 0.3 else None,
                dirigente_sindical=random.random() < 0.2,
                central_sindical=random.choice(['CUT', 'CSP-Conlutas', 'CTB', 'Força Sindical']) if random.random() < 0.4 else None,
                endereco_id=endereco.id,
                responsabilidades=random.randint(0, 1023)
            )
            session.add(militante)
            session.flush()
            
            email_militante = EmailMilitante(
                militante_id=militante.id,
                endereco_email=email
            )
            session.add(email_militante)
            
            militantes.append(militante)
            
            # Commit a cada militante para evitar transações muito longas
            session.commit()
            
        except Exception as e:
            print(f"Erro ao criar militante {i+1}: {e}")
            session.rollback()
            continue
    
    return militantes

def criar_cotas(session, militantes, quantidade_por_militante=3):
    print(f"Criando {quantidade_por_militante} cotas para cada um dos {len(militantes)} militantes...")
    for militante in militantes:
        try:
            print(f"Criando cotas para militante {militante.nome}")
            for i in range(quantidade_por_militante):
                data_base = datetime.now() - timedelta(days=30 * i)
                valor = random.uniform(50, 200)
                cota = CotaMensal(
                    militante_id=militante.id,
                    valor_antigo=valor,
                    valor_novo=valor * 1.1,
                    data_alteracao=data_base,
                    data_vencimento=data_base + timedelta(days=30),
                    pago=random.choice([True, False])
                )
                session.add(cota)
            session.commit()
        except Exception as e:
            print(f"Erro ao criar cotas para militante {militante.nome}: {e}")
            session.rollback()
            continue
    print("Cotas criadas com sucesso!")

def criar_pagamentos(militantes):
    """Cria pagamentos fictícios"""
    tipos_pagamento = ["Cota", "Jornal", "Assinatura", "Campanha Financeira"]
    for militante in militantes:
        for _ in range(random.randint(1, 5)):
            pagamento = Pagamento(
                militante_id=militante.id,
                tipo_pagamento=random.choice(tipos_pagamento),
                valor=random.uniform(50, 500),
                data_pagamento=fake.date_between(start_date='-1y', end_date='today')
            )
            db_session.add(pagamento)
    db_session.commit()

def criar_materiais_vendidos(militantes):
    """Cria materiais vendidos fictícios"""
    tipos_material = db_session.query(TipoMaterial).all()
    for militante in militantes:
        for _ in range(random.randint(1, 3)):
            material = MaterialVendido(
                militante_id=militante.id,
                tipo_material_id=random.choice(tipos_material).id,
                descricao=fake.sentence(),
                valor=random.uniform(20, 100),
                data_venda=fake.date_time_between(start_date='-1y', end_date='now')
            )
            db_session.add(material)
    db_session.commit()

def criar_vendas_jornal(militantes):
    """Cria vendas de jornal avulso fictícias"""
    for militante in militantes:
        for _ in range(random.randint(1, 4)):
            venda = VendaJornalAvulso(
                militante_id=militante.id,
                quantidade=random.randint(1, 10),
                valor_total=random.uniform(10, 100),
                data_venda=fake.date_time_between(start_date='-1y', end_date='now')
            )
            db_session.add(venda)
    db_session.commit()

def criar_assinaturas(militantes):
    """Cria assinaturas anuais fictícias"""
    tipos_material = db_session.query(TipoMaterial).all()
    for militante in militantes:
        if random.random() < 0.3:  # 30% de chance de ter assinatura
            data_inicio = fake.date_time_between(start_date='-1y', end_date='now')
            assinatura = AssinaturaAnual(
                militante_id=militante.id,
                tipo_material_id=random.choice(tipos_material).id,
                quantidade=random.randint(1, 3),
                valor_total=random.uniform(100, 500),
                data_inicio=data_inicio,
                data_fim=data_inicio + timedelta(days=365)
            )
            db_session.add(assinatura)
    db_session.commit()

def criar_relatorios():
    """Cria relatórios fictícios"""
    for _ in range(12):  # Um relatório por mês do último ano
        data = fake.date_time_between(start_date='-1y', end_date='now')
        
        relatorio_cotas = RelatorioCotasMensais(
            setor_id=random.randint(1, 5),
            comite_id=random.randint(1, 3),
            total_cotas=random.uniform(1000, 5000),
            data_relatorio=data
        )
        
        relatorio_vendas = RelatorioVendasMateriais(
            setor_id=random.randint(1, 5),
            comite_id=random.randint(1, 3),
            total_vendas=random.uniform(500, 3000),
            data_relatorio=data
        )
        
        db_session.add(relatorio_cotas)
        db_session.add(relatorio_vendas)
    
    db_session.commit()

def criar_setores():
    """Cria setores padrão"""
    setores = [
        "Setor 1",
        "Setor 2",
        "Setor 3",
        "Setor 4",
        "Setor 5"
    ]
    for setor in setores:
        if not db_session.query(Setor).filter_by(nome=setor).first():
            db_session.add(Setor(nome=setor))
    db_session.commit()

def criar_comites():
    """Cria comitês padrão"""
    comites = [
        "Comitê 1",
        "Comitê 2",
        "Comitê 3"
    ]
    for comite in comites:
        if not db_session.query(ComiteCentral).filter_by(nome=comite).first():
            db_session.add(ComiteCentral(nome=comite))
    db_session.commit()

def criar_roles():
    """Cria roles padrão"""
    roles = [
        ("admin", 1),      # Nível 1: Administrador
        ("gestor", 2),     # Nível 2: Gestor
        ("usuario", 3)     # Nível 3: Usuário comum
    ]
    for nome, nivel in roles:
        if not db_session.query(Role).filter_by(nome=nome).first():
            db_session.add(Role(nome=nome, nivel=nivel))
    db_session.commit()

def criar_usuario_admin():
    """Cria usuário admin inicial"""
    if not db_session.query(Usuario).filter_by(username='admin').first():
        role_admin = db_session.query(Role).filter_by(nome='admin').first()
        setor = db_session.query(Setor).first()
        
        admin = Usuario(
            username='admin',
            email='admin@example.com',
            is_admin=True,
            ativo=True,
            role_id=role_admin.id if role_admin else None,
            setor_id=setor.id if setor else None
        )
        admin.set_password('admin123')  # Método que deve existir na classe Usuario
        db_session.add(admin)
        db_session.commit()
        print("Usuário admin criado com sucesso!")

def seed_database():
    """Função principal para popular o banco de dados com dados fictícios"""
    print("Populando banco de dados com dados fictícios...")
    
    session = SessionLocal()
    try:
        criar_tipos_pagamento(session)
        criar_tipos_material(session)
        
        militantes = criar_militantes(session, 50)
        if militantes:
            criar_cotas(session, militantes)
            print("Dados fictícios criados com sucesso!")
    except Exception as e:
        print(f"Erro ao popular banco de dados: {e}")
        session.rollback()
    finally:
        session.close()

if __name__ == "__main__":
    seed_database() 