import unittest
from flask import Flask, g
from functions.database import db, Militante, Celula, Setor, CR, CC
from functions.permissions import (
    can_manage_militante, can_manage_celula, can_manage_setor, can_manage_cr, can_manage_cc,
    can_manage_financas, can_manage_imprensa, can_manage_responsabilidades
)

class TestPermissions(unittest.TestCase):
    def setUp(self):
        self.app = Flask(__name__)
        self.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
        self.app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
        db.init_app(self.app)
        
        with self.app.app_context():
            db.create_all()
            
            # Criar instâncias
            self.cc = CC(nome='CC 1')
            db.session.add(self.cc)
            
            self.cr = CR(nome='CR 1', cc=self.cc)
            db.session.add(self.cr)
            
            self.setor = Setor(nome='Setor 1', cr=self.cr)
            db.session.add(self.setor)
            
            self.celula = Celula(nome='Célula 1', setor=self.setor)
            db.session.add(self.celula)
            
            # Criar militantes com diferentes responsabilidades
            self.militante_basico = Militante(
                nome='Militante Básico',
                email='basico@example.com',
                celula=self.celula,
                responsabilidades=Militante.MILITANTE_BASICO
            )
            db.session.add(self.militante_basico)
            
            self.secretario_celula = Militante(
                nome='Secretário de Célula',
                email='celula@example.com',
                celula=self.celula,
                responsabilidades=Militante.SECRETARIO_CELULA
            )
            db.session.add(self.secretario_celula)
            
            self.secretario_setor = Militante(
                nome='Secretário de Setor',
                email='setor@example.com',
                celula=self.celula,
                responsabilidades=Militante.SECRETARIO_SETOR
            )
            db.session.add(self.secretario_setor)
            
            self.secretario_cr = Militante(
                nome='Secretário de CR',
                email='cr@example.com',
                celula=self.celula,
                responsabilidades=Militante.SECRETARIO_CR
            )
            db.session.add(self.secretario_cr)
            
            self.secretario_cc = Militante(
                nome='Secretário de CC',
                email='cc@example.com',
                celula=self.celula,
                responsabilidades=Militante.SECRETARIO_CC
            )
            db.session.add(self.secretario_cc)
            
            self.secretario_geral = Militante(
                nome='Secretário Geral',
                email='geral@example.com',
                celula=self.celula,
                responsabilidades=Militante.SECRETARIO_GERAL
            )
            db.session.add(self.secretario_geral)
            
            self.responsavel_financas = Militante(
                nome='Responsável de Finanças',
                email='financas@example.com',
                celula=self.celula,
                responsabilidades=Militante.RESPONSAVEL_FINANCAS
            )
            db.session.add(self.responsavel_financas)
            
            self.responsavel_imprensa = Militante(
                nome='Responsável de Imprensa',
                email='imprensa@example.com',
                celula=self.celula,
                responsabilidades=Militante.RESPONSAVEL_IMPRENSA
            )
            db.session.add(self.responsavel_imprensa)
            
            # Atribuir responsáveis às instâncias
            self.celula.responsavel_geral = self.secretario_celula
            self.celula.responsavel_financas = self.responsavel_financas
            self.celula.responsavel_imprensa = self.responsavel_imprensa
            
            self.setor.responsavel_geral = self.secretario_setor
            self.setor.responsavel_financas = self.responsavel_financas
            self.setor.responsavel_imprensa = self.responsavel_imprensa
            
            self.cr.responsavel_geral = self.secretario_cr
            self.cr.responsavel_financas = self.responsavel_financas
            self.cr.responsavel_imprensa = self.responsavel_imprensa
            
            self.cc.responsavel_geral = self.secretario_cc
            self.cc.responsavel_financas = self.responsavel_financas
            self.cc.responsavel_imprensa = self.responsavel_imprensa
            
            db.session.commit()
    
    def test_can_manage_militante(self):
        with self.app.app_context():
            # Militante básico não pode gerenciar outros militantes
            g.user = type('User', (), {'militante': self.militante_basico})
            self.assertFalse(can_manage_militante(self.militante_basico.id))
            
            # Secretário de célula pode gerenciar militantes da sua célula
            g.user = type('User', (), {'militante': self.secretario_celula})
            self.assertTrue(can_manage_militante(self.militante_basico.id))
            
            # Secretário de setor pode gerenciar militantes do seu setor
            g.user = type('User', (), {'militante': self.secretario_setor})
            self.assertTrue(can_manage_militante(self.militante_basico.id))
            
            # Secretário de CR pode gerenciar militantes do seu CR
            g.user = type('User', (), {'militante': self.secretario_cr})
            self.assertTrue(can_manage_militante(self.militante_basico.id))
            
            # Secretário de CC pode gerenciar militantes do seu CC
            g.user = type('User', (), {'militante': self.secretario_cc})
            self.assertTrue(can_manage_militante(self.militante_basico.id))
            
            # Secretário Geral pode gerenciar qualquer militante
            g.user = type('User', (), {'militante': self.secretario_geral})
            self.assertTrue(can_manage_militante(self.militante_basico.id))
    
    def test_can_manage_financas(self):
        with self.app.app_context():
            # Militante básico não pode gerenciar finanças
            g.user = type('User', (), {'militante': self.militante_basico})
            self.assertFalse(can_manage_financas(self.celula.id, 'celula'))
            
            # Responsável de finanças pode gerenciar finanças da sua instância
            g.user = type('User', (), {'militante': self.responsavel_financas})
            self.assertTrue(can_manage_financas(self.celula.id, 'celula'))
            self.assertTrue(can_manage_financas(self.setor.id, 'setor'))
            self.assertTrue(can_manage_financas(self.cr.id, 'cr'))
            self.assertTrue(can_manage_financas(self.cc.id, 'cc'))
            
            # Secretário Geral pode gerenciar finanças de qualquer instância
            g.user = type('User', (), {'militante': self.secretario_geral})
            self.assertTrue(can_manage_financas(self.celula.id, 'celula'))
            self.assertTrue(can_manage_financas(self.setor.id, 'setor'))
            self.assertTrue(can_manage_financas(self.cr.id, 'cr'))
            self.assertTrue(can_manage_financas(self.cc.id, 'cc'))
    
    def test_can_manage_imprensa(self):
        with self.app.app_context():
            # Militante básico não pode gerenciar imprensa
            g.user = type('User', (), {'militante': self.militante_basico})
            self.assertFalse(can_manage_imprensa(self.celula.id, 'celula'))
            
            # Responsável de imprensa pode gerenciar imprensa da sua instância
            g.user = type('User', (), {'militante': self.responsavel_imprensa})
            self.assertTrue(can_manage_imprensa(self.celula.id, 'celula'))
            self.assertTrue(can_manage_imprensa(self.setor.id, 'setor'))
            self.assertTrue(can_manage_imprensa(self.cr.id, 'cr'))
            self.assertTrue(can_manage_imprensa(self.cc.id, 'cc'))
            
            # Secretário Geral pode gerenciar imprensa de qualquer instância
            g.user = type('User', (), {'militante': self.secretario_geral})
            self.assertTrue(can_manage_imprensa(self.celula.id, 'celula'))
            self.assertTrue(can_manage_imprensa(self.setor.id, 'setor'))
            self.assertTrue(can_manage_imprensa(self.cr.id, 'cr'))
            self.assertTrue(can_manage_imprensa(self.cc.id, 'cc'))
    
    def test_can_manage_responsabilidades(self):
        with self.app.app_context():
            # Militante básico não pode gerenciar responsabilidades
            g.user = type('User', (), {'militante': self.militante_basico})
            self.assertFalse(can_manage_responsabilidades(self.militante_basico.id))
            
            # Secretário de setor pode gerenciar responsabilidades do seu setor
            g.user = type('User', (), {'militante': self.secretario_setor})
            self.assertTrue(can_manage_responsabilidades(self.militante_basico.id))
            
            # Secretário de CR pode gerenciar responsabilidades do seu CR
            g.user = type('User', (), {'militante': self.secretario_cr})
            self.assertTrue(can_manage_responsabilidades(self.militante_basico.id))
            
            # Secretário de CC pode gerenciar responsabilidades do seu CC
            g.user = type('User', (), {'militante': self.secretario_cc})
            self.assertTrue(can_manage_responsabilidades(self.militante_basico.id))
            
            # Secretário Geral pode gerenciar responsabilidades de qualquer militante
            g.user = type('User', (), {'militante': self.secretario_geral})
            self.assertTrue(can_manage_responsabilidades(self.militante_basico.id))

if __name__ == '__main__':
    unittest.main() 