<?php

namespace App\Http\Controllers\Admin\Servidor;

use App\Enums\EstadoCivilEnum;
use App\Enums\FiltroBuscaServidorEnum;
use App\Enums\MotivoDesfiliacaoDefinitivaEnum;
use App\Enums\MotivoDesfiliacaoTemporariaEnum;
use App\Enums\NivelEnsinoEnum;
use App\Enums\ProventoAposentadoEnum;
use App\Enums\RegimeServidorEnum;
use App\Enums\SexoEnum;
use App\Enums\SituacaoServidorBuscaEnum;
use App\Enums\TipoAposentadoriaEnum;
use App\Enums\TipoDesligamentoSindicatoEnum;
use App\Http\Controllers\Controller;
use App\Http\Requests\AfiliaServidorRequest;
use App\Http\Requests\AtualizaFalecimentoRequest;
use App\Http\Requests\DesfiliaServidorRequest;
use App\Http\Requests\ServidorStoreRequest;
use App\Http\Requests\ServidorUpdateRequest;
use App\Models\Cargo;
use App\Models\Endereco;
use App\Models\Logradouro\Estado;
use App\Models\MotivoFiliacao;
use App\Models\NivelSalarial;
use App\Models\RegistroServidor;
use App\Models\Servidor;
use App\Models\UnidadeOrganizacional;
use App\Services\AfiliaSindicatoService;
use App\Services\DesfiliaSindicatoService;
use App\Services\ReafiliaSindicatoService;
use App\Services\ReligaExtraordinariamenteService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ServidorController extends Controller
{
    public function __construct()
    {
        $this->middleware(['role:admin']);
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $excluidos = $request->input('excluidos', 'off') == 'on' ? true : false;

        $situacao = SituacaoServidorBuscaEnum::make((int) $request->input('situacao', 4)); // 4 = Todos
        $filtro = FiltroBuscaServidorEnum::make((int) $request->input('filtro', 0)); // 0 =  Nome
        $servidores = Servidor::with(['registros' => function ($query) {
            $query->ativos()->first();
        }])->busca($filtro, $request->busca, $situacao, $excluidos)->paginate();

        return view('admin.servidores.index', [
            'servidores' => $servidores,
            'nome' => $request->nome,
            'filtroSelecionado' => $filtro,
            'filtrosServidores' => FiltroBuscaServidorEnum::getAll(),
            'situacoesServidores' => SituacaoServidorBuscaEnum::getAll(),
            'situacaoSelecionada' => $situacao,
            'busca' => $request->busca,
            'excluidos' => $excluidos,
            'registro' => $request->registro
        ]);
    }

    public function create(Request $request)
    {
        $sexos = SexoEnum::getAll();
        $estadosCivis = EstadoCivilEnum::getAll();
        $cargos = Cargo::all();
        $unidades = UnidadeOrganizacional::all();
        $estados = Estado::orderBy('ufe_sg')->select('ufe_sg')->get();
        $regimes = RegimeServidorEnum::getAll();
        $proventos = ProventoAposentadoEnum::getAll();
        $tiposAposentadoria = TipoAposentadoriaEnum::getAll();
        $niveisEnsino = NivelEnsinoEnum::getAll();
        $niveisSalariais = NivelSalarial::all();

        return view('admin.servidores.create', [
            'sexos' => $sexos,
            'estadosCivis' => $estadosCivis,
            'niveisEnsino' => $niveisEnsino,
            'cargos' => $cargos,
            'unidades' => $unidades,
            'estados' => $estados,
            'regimes' => $regimes,
            'proventos' => $proventos,
            'tiposAposentadoria' => $tiposAposentadoria,
            'niveisSalariais' => $niveisSalariais,
            'redirectTo' => $request->redirectTo
        ]);
    }

    public function createSimplificado(Request $request)
    {
        $sexos = SexoEnum::getAll();
        $estadosCivis = EstadoCivilEnum::getAll();
        $cargos = Cargo::all();
        $unidades = UnidadeOrganizacional::all();
        $estados = Estado::orderBy('ufe_sg')->select('ufe_sg')->get();
        $regimes = RegimeServidorEnum::getAll();
        $proventos = ProventoAposentadoEnum::getAll();
        $tiposAposentadoria = TipoAposentadoriaEnum::getAll();
        $niveisEnsino = NivelEnsinoEnum::getAll();

        return view('admin.servidores.create-simplificado', [
            'sexos' => $sexos,
            'estadosCivis' => $estadosCivis,
            'cargos' => $cargos,
            'unidades' => $unidades,
            'estados' => $estados,
            'regimes' => $regimes,
            'proventos' => $proventos,
            'tiposAposentadoria' => $tiposAposentadoria,
            'niveisEnsino' => $niveisEnsino,
            'redirectTo' => $request->redirectTo
        ]);
    }

    public function store(ServidorStoreRequest $request)
    {
        $servidor = new Servidor($request->only(
            'nome',
            'nome_social',
            'cpf',
            'rg',
            'nao_perturbe',
            'data_nascimento',
            'nacionalidade',
            'naturalidade',
            'naturalidade_uf',
            'nome_pai',
            'nome_mae',
            'observacoes'
        ));
        $registro = new RegistroServidor($request->only('cargo_id', 'readaptado', 'data_admissao', 'data_desligamento', 'unidadeorganizacional_id', 'nivel_salarial_id'));
        $registro->numero = $request->numero_registro;
        $registro->regime = $request->regime ? RegimeServidorEnum::make((int) $request->regime) : null;

        $servidor->estado_civil = $request->estado_civil ? EstadoCivilEnum::make((int) $request->estado_civil) : null;
        $servidor->sexo = $request->sexo ? SexoEnum::make((int) $request->sexo) : null;
        $servidor->nivel_ensino = $request->nivel_ensino ? NivelEnsinoEnum::make((int) $request->nivel_ensino) : null;

        if ($request->cargo_id) {
            $cargo = Cargo::find($request->cargo_id);
            $registro->cargo()->associate($cargo);
        }

        if ($request->cargoreadaptado_id) {
            $cargo = Cargo::find($request->cargoreadaptado_id);
            $registro->cargoReadaptado()->associate($cargo);
        }

        if ($registro->regime->isAposentado()) {
            $registro->fill($request->only('data_aposentadoria', 'portaria_aposentadoria', 'paridade'));
            $registro->tipo_aposentadoria = $request->tipo_aposentadoria ? TipoAposentadoriaEnum::make((int) $request->tipo_aposentadoria) : null;
            $registro->proventos = $request->proventos ? ProventoAposentadoEnum::make((int) $request->proventos) : null;
        } else {
            $registro->data_aposentadoria = null;
            $registro->portaria_aposentadoria = null;
            $registro->paridade = null;
            $registro->tipo_aposentadoria = null;
            $registro->proventos = null;
        }

        DB::beginTransaction();

        $servidor->save();
        $servidor->saveTelefones($request->telefone ?? []);
        $servidor->saveEmails($request->email ?? []);
        $servidor->registros()->save($registro);

        if ($request->unidadeorganizacional_id) {
            $unidade = UnidadeOrganizacional::find($request->unidadeorganizacional_id);
            $registro->unidadeOrganizacional()->associate($unidade);

            if ($request->cep_lotacao) {
                $endereco = new Endereco();
                $endereco->cep = $request->cep_lotacao;
                $endereco->numero = $request->numero_lotacao;
                $endereco->logradouro = $request->logradouro_lotacao;
                $endereco->bairro = $request->bairro_lotacao;
                $endereco->cidade = $request->cidade_lotacao;
                $endereco->estado = $request->estado_lotacao;
                $endereco->observacoes = $request->observacoes_lotacao;

                $registro->enderecos()->save($endereco);
            }
        }

        if ($request->imagem_camera) {
            $servidor->saveImagem($request->imagem_camera);
            $servidor->save();
        }

        if ($request->cep) {
            $endereco = new Endereco($request->only('cep', 'logradouro', 'numero', 'cidade', 'bairro', 'estado', 'complemento', 'aceita_mala_direta'));
            $endereco->observacoes = $request->observacoes_endereco;
            $servidor->enderecos()->save($endereco);
        }

        DB::commit();

        if ($request->redirect_to) {
            return redirect(url($request->redirect_to . '/' . $servidor->id));
        }

        return redirect()
            ->route('admin.servidores.edit', ['servidor' => $servidor])
            ->with('status', 'Servidor incluído com sucesso!')
            ->with('sucessoInclusao', true)
            ->with('rotaVoltar', route('admin.servidores.index'));
    }

    public function afiliaForm(Servidor $servidor)
    {
        return view('admin.servidores.afilia', [
            'servidor' => $servidor,
            'matriculaDesligadaTemporariamente' => $servidor->matriculas()->desligadaTemporariamente()->first(),
            'motivos' => MotivoFiliacao::orderBy('id')->get(),
        ]);
    }

    public function afilia(AfiliaServidorRequest $request, Servidor $servidor)
    {
        $motivo = MotivoFiliacao::find($request->motivo_filiacao);

        if ($servidor->desfiliadoTemporariamente()) {
            $service = new ReafiliaSindicatoService($servidor);
            $service->reafilia();
        } else {
            $dataFiliacao = Carbon::createFromFormat('d/m/Y', $request->data_filiacao);
            $service = new AfiliaSindicatoService($servidor, $motivo, $dataFiliacao, $request->motivo_filiacao_outros);
            $service->afilia();
        }

        return redirect()
            ->route('admin.servidores.edit', ['servidor' => $servidor])
            ->with('sucessoFiliacao', true)
            ->with('status', 'Servidor afiliado com sucesso!');
    }

    public function desfiliaForm(Servidor $servidor)
    {
        $matricula = $servidor->matriculas()->latest()->first();
        $motivosDefinitivo = MotivoDesfiliacaoDefinitivaEnum::getAll();
        $motivosTemporario = MotivoDesfiliacaoTemporariaEnum::getAll();

        return view('admin.servidores.desfilia', [
            'servidor' => $servidor,
            'matricula' => $matricula,
            'tipos' => TipoDesligamentoSindicatoEnum::getAll(),
            'motivosDefinitivo' => $motivosDefinitivo,
            'motivosTemporario' => $motivosTemporario,
        ]);
    }

    public function desfilia(DesfiliaServidorRequest $request, Servidor $servidor)
    {
        if ($request->motivo_desligamento_temporario) {
            $motivoDesligamento = MotivoDesfiliacaoTemporariaEnum::make((int) $request->motivo_desligamento_temporario);
        } else {
            $motivoDesligamento = MotivoDesfiliacaoDefinitivaEnum::make((int) $request->motivo_desligamento_definitivo);
        }

        $tipoDefault = TipoDesligamentoSindicatoEnum::definitivo()->getIndex();
        $tipo = TipoDesligamentoSindicatoEnum::make((int) $request->input('tipo_desligamento', $tipoDefault));

        if ($request->data_falecimento) {
            $dataFalecimento = Carbon::createFromFormat('d/m/Y', $request->data_falecimento);
        } else {
            $dataFalecimento = null;
        }

        if ($request->data_publicacao_portaria) {
            $dataPortaria = Carbon::createFromFormat('d/m/Y', $request->data_publicacao_portaria);
        } else {
            $dataPortaria = null;
        }

        $dataDesligamento = Carbon::createFromFormat('d/m/Y', $request->data_desligamento);
        $service = new DesfiliaSindicatoService(
            $servidor,
            $motivoDesligamento,
            $tipo,
            $dataDesligamento,
            $dataPortaria,
            $dataFalecimento,
            $request->mes_ano_parou_desconto
        );

        $service->desfilia();

        $redirect = redirect()
            ->route('admin.servidores.edit', ['servidor' => $servidor])
            ->with('status', 'Servidor desfiliado com sucesso!');

        if ($tipo->isDefinitivo()) {
            $redirect->with('termos-assinar', true);
        }

        return $redirect;
    }

    public function religamentoExtraordinarioForm(Servidor $servidor)
    {
        if (!$servidor->desfiliadoDefinitivamente()) {
            return redirect()->back()->with('status', 'Servidor não está desligado definitivamente');
        }

        $matricula = $servidor->matriculas()->desligadaDefinitivamente()->latest()->first();

        return view('admin.servidores.religamento-extraordinario', [
            'servidor' => $servidor,
            'matricula' => $matricula,
        ]);
    }


    public function religaExtraordinariamente(Request $request, Servidor $servidor)
    {
        $this->validate($request, [
            'motivo_religamento_extraordinario' => 'string|required|max:150',
            'data_religamento_extraordinario' => 'required|date_format:d/m/Y',
        ]);

        $data = Carbon::createFromFormat('d/m/Y', $request->data_religamento_extraordinario);
        $service = new ReligaExtraordinariamenteService($servidor, $request->motivo_religamento_extraordinario, $data);
        $service->religa();

        return redirect()
            ->route('admin.servidores.edit', ['servidor' => $servidor])
            ->with('status', 'Servidor religado com sucesso!');
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Servidor  $servidor
     * @return \Illuminate\Http\Response
     */
    public function edit(Servidor $servidor)
    {
        $servidorEAssociado = $servidor->eAssociado();
        $servidorDesfiliadoTemporariamente = $servidor->desfiliadoTemporariamente();
        $servidorDesfiliadoDefinitivamente = $servidor->desfiliadoDefinitivamente();
        $sexos = SexoEnum::getAll();
        $estadosCivis = EstadoCivilEnum::getAll();
        $documentosImprimirDesligamento = $this->documentosServidorImprimirDesligamento($servidor);
        $documentosImprimirFiliacao = $this->documentosServidorImprimirFiliacao($servidor);
        $todosDocumentosImprimir = $documentosImprimirFiliacao->merge($documentosImprimirDesligamento);
        $estados = Estado::orderBy('ufe_sg')->select('ufe_sg')->get();
        $niveisEnsino = NivelEnsinoEnum::getAll();
        $motivosExoneracao = [
            MotivoDesfiliacaoDefinitivaEnum::demitido(),
            MotivoDesfiliacaoDefinitivaEnum::exoneracao(),
            MotivoDesfiliacaoDefinitivaEnum::terminoContrato()
        ];
        if ($servidorEAssociado || $servidorDesfiliadoTemporariamente) {
            $matricula = $servidor->matricula();
        } else if ($servidorDesfiliadoDefinitivamente) {
            $matricula = $servidor->matriculaDesligadaDefinitivamente();
        } else {
            $matricula = null;
        }

        return view('admin.servidores.edit', [
            'servidor' => $servidor,
            'sexos' => $sexos,
            'estados' => $estados,
            'documentosImprimirDesligamento' => $documentosImprimirDesligamento,
            'documentosImprimirFiliacao' => $documentosImprimirFiliacao,
            'todosDocumentosImprimir' => $todosDocumentosImprimir,
            'estadosCivis' => $estadosCivis,
            'niveisEnsino' => $niveisEnsino,
            'matricula' => $matricula,
            'motivosExoneracao' => $motivosExoneracao,
            'servidorEAssociado' => $servidorEAssociado,
            'servidorDesfiliadoTemporariamente' => $servidorDesfiliadoTemporariamente,
            'servidorDesfiliadoDefinitivamente' => $servidorDesfiliadoDefinitivamente,
        ]);
    }

    private function documentosServidorImprimirDesligamento(Servidor $servidor)
    {
        $documentos = collect();

        if ($servidor->desfiliadoDefinitivamente()) {
            $documentos->push((object) [
                'url' => route('admin.formularios.servidores.desfiliacao', ['servidor' => $servidor]),
                'texto' => 'Desligamento do sindicato'
            ]);

            if ($servidor->teveSeguroCanceladoAoDesfiliar()) {
                $documentos->push((object) [
                    'url' => route('admin.formularios.servidores.cancelamento-seguro', ['servidor' => $servidor]),
                    'texto' => 'Cancelamento do seguro'
                ]);
            }

            if ($servidor->teveOsanCanceladaAoDesfiliar()) {
                $documentos->push((object) [
                    'url' => route('admin.formularios.servidores.cancelamento-osan', ['servidor' => $servidor]),
                    'texto' => 'Cancelamento da OSAN'
                ]);
            }

            if ($servidor->temProcessosJuridicos()) {
                $documentos->push((object) [
                    'url' => route('admin.formularios.servidores.desfiliacao-renuncia-poderes-advogados', ['servidor' => $servidor]),
                    'texto' => 'Renúncia aos poderes outorgados aos advogados'
                ]);
            }
        }

        return $documentos;
    }

    private function documentosServidorImprimirFiliacao(Servidor $servidor)
    {
        $documentos = collect();

        if ($servidor->eAssociadoOuDesfiliado()) {
            $documentos->push((object) [
                'url' => route('admin.formularios.servidores.ficha-inscricao', ['servidor' => $servidor]),
                'texto' => 'Ficha de inscrição'
            ]);
        }

        if ($servidor->eAssociado()) {
            $matriculaAtiva = $servidor->matriculas()->latest()->first();
            $mesesDoNascimentoAteAfiliacao = optional($servidor->data_nascimento)->diffInMonths($matriculaAtiva->data_filiacao) ?? 0;
            if ($mesesDoNascimentoAteAfiliacao >= 791) {
                // 65 anos e 11 meses
                $documentos->push((object) [
                    'url' => route('admin.formularios.servidores.declaracao-idade-acima-limite', ['servidor' => $servidor]),
                    'texto' => 'Declaração acima idade limite para Seguro de Vida'
                ]);
            }
        }

        return $documentos;
    }

    public function update(ServidorUpdateRequest $request, Servidor $servidor)
    {
        $servidor->fill($request->only(
            'nome',
            'nome_social',
            'cpf',
            'rg',
            'nao_perturbe',
            'data_nascimento',
            'nacionalidade',
            'naturalidade',
            'naturalidade_uf',
            'nome_pai',
            'nome_mae',
            'observacoes'
        ));
        $servidor->estado_civil = $request->estado_civil ? EstadoCivilEnum::make((int) $request->estado_civil) : null;
        $servidor->sexo = $request->sexo ? SexoEnum::make((int) $request->sexo) : null;
        $servidor->nivel_ensino = $request->nivel_ensino ? NivelEnsinoEnum::make((int) $request->nivel_ensino) : null;

        DB::beginTransaction();
        $servidor->save();
        $servidor->saveTelefones($request->telefone ?? []);
        $servidor->saveEmails($request->email ?? []);
        DB::commit();

        if ($request->imagem_camera) {
            $servidor->saveImagem($request->imagem_camera);
            $servidor->save();
        } elseif ($request->remover_imagem) {
            $servidor->removeImagem();
            $servidor->save();
        }

        return redirect()
            ->route('admin.servidores.edit', ['servidor' => $servidor])
            ->with('status', 'Servidor editado com sucesso!')
            ->with('sucesso', true)
            ->with('rotaVoltar', route('admin.servidores.index'));
    }

    public function falecimentoForm(Servidor $servidor)
    {
        $estados = Estado::orderBy('ufe_sg')->select('ufe_sg')->get();
        $endereco = optional($servidor->herdeiro)->endereco;
        $telefoneFixo = optional($servidor->herdeiro)->contatos()->telefonesFixos()->first();
        $telefoneCelular = optional($servidor->herdeiro)->contatos()->telefonesCelulares()->first();

        return view('admin.servidores.falecimento', [
            'servidor' => $servidor,
            'estados' => $estados,
            'herdeiro' => $servidor->hedeiro,
            'endereco' => $endereco,
            'telefoneFixo' => $telefoneFixo,
            'telefoneCelular' => $telefoneCelular,
        ]);
    }

    public function atualizaFalecimento(AtualizaFalecimentoRequest $request, Servidor $servidor)
    {
        DB::beginTransaction();

        if ($request->nome_herdeiro) {
            $herdeiro = $servidor->herdeiro->fill(['nome' => $request->nome_herdeiro]);

            $endereco = $herdeiro->endereco;
            $endereco->fill($request->only('cep', 'logradouro', 'numero', 'cidade', 'bairro', 'estado', 'complemento'));
            $endereco->observacoes = $request->observacoes_endereco;

            $herdeiro->save();
            $herdeiro->saveTelefones($request->telefone ?? []);
            if ($endereco) {
                $herdeiro->endereco()->save($endereco);
            }
        }

        $servidor->falecido = true;
        $servidor->data_falecimento = $request->data_falecimento;
        $servidor->observacao_falecimento = $request->observacao_falecimento;
        $servidor->save();

        DB::commit();

        return redirect()
            ->route('admin.servidores.edit', ['servidor' => $servidor])
            ->with('status', 'Falecimento atualizado com sucesso!');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Servidor  $servidor
     * @return \Illuminate\Http\Response
     */
    public function destroy(Servidor $servidor)
    {
        $servidor->delete();

        return redirect()
            ->back()
            ->with('status', 'Servidor excluído com sucesso!');
    }

    public function restore(Servidor $servidor)
    {
        $servidor->withTrashed()->restore();

        return redirect()
            ->back()
            ->with('status', 'Servidor restaurado com sucesso!');
    }

    public function getEnderecoUnidadeOrganizacional($idUnidade)
    {
        $unidade = UnidadeOrganizacional::find($idUnidade);
        $endereco = $unidade->enderecos()->firstOrFail();

        return ['endereco' => $endereco->extenso()];
    }
}
