<?php

namespace Tests\Unit;

use App\Enums\MotivoDesfiliacaoDefinitivaEnum;
use App\Enums\MotivoDesfiliacaoTemporariaEnum;
use App\Enums\TipoDesligamentoSindicatoEnum;
use App\Exceptions\ValidationException;
use App\Models\Matricula;
use App\Models\MotivoFiliacao;
use App\Models\Servidor;
use App\Services\AfiliaSindicatoService;
use App\Services\DesfiliaSindicatoService;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\RefreshDatabase;
use MotivoFiliacaoSeeder;
use Tests\TestCase as TestCase;

class DesfiliaSindicatoServiceTest extends TestCase
{
    use RefreshDatabase;

    public function setUp(): void
    {
        parent::setUp();

        $this->seed(MotivoFiliacaoSeeder::class);
    }

    public function test_valida()
    {
        $servidor = factory(Servidor::class)->create();
        $serviceAfilia = new AfiliaSindicatoService($servidor, MotivoFiliacao::first(), today());
        $serviceAfilia->afilia();

        $serviceDesfilia = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoDefinitivaEnum::demitido(), TipoDesligamentoSindicatoEnum::temporario(), today());
        $this->assertTrue($serviceDesfilia->valida());
    }

    public function test_valida_nao_filiado()
    {
        $servidor = factory(Servidor::class)->create();

        $serviceDesfilia = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoDefinitivaEnum::demitido(), TipoDesligamentoSindicatoEnum::temporario(), today());
        $this->expectException(ValidationException::class);

        $serviceDesfilia->valida();
    }

    public function test_desfilia_temporario()
    {
        $servidor = factory(Servidor::class)->create();
        $serviceAfilia = new AfiliaSindicatoService($servidor, MotivoFiliacao::first(), today());
        $serviceAfilia->afilia();

        $serviceDesfilia = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoTemporariaEnum::ausente(), TipoDesligamentoSindicatoEnum::temporario(), today());
        $matricula = $serviceDesfilia->desfilia();

        $this->assertInstanceOf(Matricula::class, $matricula);
        $this->assertFalse($matricula->wasRecentlyCreated);
        $this->assertTrue($matricula->tipo_desligamento->isTemporario());
    }

    public function test_desfilia_definitivo_com_matricula_ativa()
    {
        $servidor = factory(Servidor::class)->create();
        $serviceAfilia = new AfiliaSindicatoService($servidor, MotivoFiliacao::first(), today());
        $serviceAfilia->afilia();

        $serviceDesfilia = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoDefinitivaEnum::demitido(), TipoDesligamentoSindicatoEnum::definitivo(), today());
        $matricula = $serviceDesfilia->desfilia();

        $this->assertInstanceOf(Matricula::class, $matricula);
        $this->assertFalse($matricula->wasRecentlyCreated);
        $this->assertTrue($matricula->tipo_desligamento->isDefinitivo());
    }

    public function test_desfilia_definitivo_com_matricula_desligada_temporariamente()
    {
        $servidor = factory(Servidor::class)->create();
        $serviceAfilia = new AfiliaSindicatoService($servidor, MotivoFiliacao::first(), today());
        $serviceAfilia->afilia();

        $serviceDesfilia1 = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoTemporariaEnum::ausente(), TipoDesligamentoSindicatoEnum::temporario(), today());
        $serviceDesfilia1->desfilia();

        $serviceDesfilia2 = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoDefinitivaEnum::exoneracao(), TipoDesligamentoSindicatoEnum::definitivo(), today());
        $matriculaDesligadaDefinitivamente = $serviceDesfilia2->desfilia();

        $this->assertInstanceOf(Matricula::class, $matriculaDesligadaDefinitivamente);
        $this->assertFalse($matriculaDesligadaDefinitivamente->wasRecentlyCreated);
        $this->assertTrue($matriculaDesligadaDefinitivamente->tipo_desligamento->isDefinitivo());
    }

    public function test_desfilia_definitivo_falecido_data_falecimento_preenchido()
    {
        $servidor = factory(Servidor::class)->create();
        $serviceAfilia = new AfiliaSindicatoService($servidor, MotivoFiliacao::first(), today());
        $serviceAfilia->afilia();

        $dataFalecimento = Carbon::createFromFormat('d/m/Y', '27/01/2021');
        $serviceDesfilia = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoDefinitivaEnum::falecido(), TipoDesligamentoSindicatoEnum::definitivo(), today(), null, $dataFalecimento);
        $matricula = $serviceDesfilia->desfilia();
        $servidor->refresh();
        $this->assertTrue($servidor->falecido);
        $this->assertEquals($dataFalecimento->format('d/m/Y'), $servidor->data_falecimento->format('d/m/Y'));
        $this->assertInstanceOf(Matricula::class, $matricula);
        $this->assertFalse($matricula->wasRecentlyCreated);
        $this->assertTrue($matricula->tipo_desligamento->isDefinitivo());
    }

    public function test_desfilia_definitivo_falecido_data_falecimento_nao_preenchido()
    {
        $servidor = factory(Servidor::class)->create();
        $serviceAfilia = new AfiliaSindicatoService($servidor, MotivoFiliacao::first(), today());
        $serviceAfilia->afilia();

        $serviceDesfilia = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoDefinitivaEnum::falecido(), TipoDesligamentoSindicatoEnum::definitivo(), today(), null, null);
        $matricula = $serviceDesfilia->desfilia();
        $servidor->refresh();
        $this->assertTrue($servidor->falecido);
        $this->assertEquals(null, $servidor->data_falecimento);
        $this->assertInstanceOf(Matricula::class, $matricula);
        $this->assertFalse($matricula->wasRecentlyCreated);
        $this->assertTrue($matricula->tipo_desligamento->isDefinitivo());
    }

    public function test_desfilia_definitivo_exonerado_demitido_termino_contrato_data_portaria_preenchido()
    {
        $servidor = factory(Servidor::class)->create();
        $serviceAfilia = new AfiliaSindicatoService($servidor, MotivoFiliacao::first(), today());
        $serviceAfilia->afilia();

        $dataPortaria = Carbon::createFromFormat('d/m/Y', '27/01/2021');
        $serviceDesfilia = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoDefinitivaEnum::exoneracao(), TipoDesligamentoSindicatoEnum::definitivo(), today(), $dataPortaria, null);
        $matricula = $serviceDesfilia->desfilia();
        $servidor->refresh();
        $this->assertEquals($dataPortaria->format('d/m/Y'), $matricula->data_publicacao_portaria->format('d/m/Y'));
        $this->assertInstanceOf(Matricula::class, $matricula);
        $this->assertFalse($matricula->wasRecentlyCreated);
        $this->assertTrue($matricula->tipo_desligamento->isDefinitivo());
    }

    public function test_desfilia_definitivo_exonerado_demitido_termino_contrato_data_portaria_nao_preenchido()
    {
        $servidor = factory(Servidor::class)->create();
        $serviceAfilia = new AfiliaSindicatoService($servidor, MotivoFiliacao::first(), today());
        $serviceAfilia->afilia();

        $serviceDesfilia = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoDefinitivaEnum::exoneracao(), TipoDesligamentoSindicatoEnum::definitivo(), today(), null);
        $matricula = $serviceDesfilia->desfilia();
        $servidor->refresh();
        $this->assertEquals(null, $matricula->data_publicacao_portaria);
        $this->assertInstanceOf(Matricula::class, $matricula);
        $this->assertFalse($matricula->wasRecentlyCreated);
        $this->assertTrue($matricula->tipo_desligamento->isDefinitivo());
    }

    public function test_desfilia_temporario_mes_ano_parou_desconto_nao_preenchido()
    {
        $servidor = factory(Servidor::class)->create();
        $serviceAfilia = new AfiliaSindicatoService($servidor, MotivoFiliacao::first(), today());
        $serviceAfilia->afilia();

        $serviceDesfilia = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoTemporariaEnum::ausente(), TipoDesligamentoSindicatoEnum::temporario(), today(), null, null, null);
        $matricula = $serviceDesfilia->desfilia();
        $servidor->refresh();
        $this->assertEquals(null, $matricula->mes_ano_parou_desconto);
        $this->assertInstanceOf(Matricula::class, $matricula);
        $this->assertFalse($matricula->wasRecentlyCreated);
        $this->assertTrue($matricula->tipo_desligamento->isTemporario());
    }

    public function test_desfilia_temporario_mes_ano_parou_desconto_preenchido()
    {
        $servidor = factory(Servidor::class)->create();
        $serviceAfilia = new AfiliaSindicatoService($servidor, MotivoFiliacao::first(), today());
        $serviceAfilia->afilia();

        $serviceDesfilia = new DesfiliaSindicatoService($servidor, MotivoDesfiliacaoTemporariaEnum::ausente(), TipoDesligamentoSindicatoEnum::temporario(), today(), null, null, '10/2022');
        $matricula = $serviceDesfilia->desfilia();
        $servidor->refresh();
        $this->assertEquals('10/2022', $matricula->mes_ano_parou_desconto);
        $this->assertInstanceOf(Matricula::class, $matricula);
        $this->assertFalse($matricula->wasRecentlyCreated);
        $this->assertTrue($matricula->tipo_desligamento->isTemporario());
    }
}
