<?php

namespace App\Http\Controllers\Admin;

use App\Enums\FormaPagamentoContaPagarEnum;
use App\Enums\FormaPagamentoContaReceberEnum;
use App\Enums\RecorrenciaContaPagaReceberEnum;
use App\Enums\StatusContaPagarEnum;
use App\Enums\TipoContaPagarReceberEnum;
use App\Enums\TipoDespesaContaPagarReceberEnum;
use App\Http\Controllers\Controller;
use App\Http\Requests\ContaPagarStoreRequest;
use App\Http\Requests\ContaPagarUpdateRequest;
use App\Http\Requests\ContaReceberStoreRequest;
use App\Http\Requests\ContaReceberUpdateRequest;
use App\Models\ClassificacaoConta;
use App\Models\ContaPagarReceber;
use App\Models\PlanoConta;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class ContaPagarReceberController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $vencimento = $request->vencimento ? $this->vencimento($request->vencimento) : [];

        $filtroStatus = $request->status
            ? StatusContaPagarEnum::make((int) $request->status)
            : StatusContaPagarEnum::todos();

        $contas = ContaPagarReceber::orderBy('data_pagamento', 'desc')->search($request->busca, $filtroStatus, $vencimento)->paginate();
        $statuses = StatusContaPagarEnum::getAll();
        $tipos = TipoContaPagarReceberEnum::getAll();
        $tiposDespesa = TipoDespesaContaPagarReceberEnum::getAll();
        $recorrencias = RecorrenciaContaPagaReceberEnum::getAll();
        $formasPagamento = FormaPagamentoContaPagarEnum::getAll();

        return view('admin.contas-pagar-receber.index', [
            'contas' => $contas,
            'statuses' => $statuses,
            'tipos' => $tipos,
            'tiposDespesa' => $tiposDespesa,
            'recorrencias' => $recorrencias,
            'formasPagamento' => $formasPagamento,
            'filtroStatus' => $filtroStatus,
            'vencimento' => $request->vencimento
        ]);
    }

    private function vencimento(string $vencimento)
    {
        $venc = collect(explode('-', $vencimento));
        $inicio = Carbon::createFromFormat('d/m/Y', trim($venc[0]))->setTime(0, 0, 0);
        $fim = Carbon::createFromFormat('d/m/Y', trim($venc[1]))->setTime(23, 59);
        return [$inicio, $fim];
    }

    /**
     * Retorna todos os status exceto o "todos", utilizado apenas para busca
     */
    private function statusSelecionaveis()
    {
        return collect(StatusContaPagarEnum::getAll())
            ->filter(function ($enum) {
                if ($enum->isTodos() || $enum->isVencido()) {
                    return false;
                }

                return true;
            })->toArray();
    }

    public function createReceber()
    {
        $statuses = $this->statusSelecionaveis();
        $formasRecebimento = FormaPagamentoContaReceberEnum::getAll();

        return view('admin.contas-pagar-receber.create-receber', [
            'statuses' => $statuses,
            'formasRecebimento' => $formasRecebimento,
        ]);
    }

    public function createPagar()
    {
        $statuses = $this->statusSelecionaveis();
        $tiposDespesa = TipoDespesaContaPagarReceberEnum::getAll();
        $recorrencias = RecorrenciaContaPagaReceberEnum::getAll();
        $formasPagamento = FormaPagamentoContaPagarEnum::getAll();
        $planosContas = PlanoConta::all();

        return view('admin.contas-pagar-receber.create-pagar', [
            'statuses' => $statuses,
            'tiposDespesa' => $tiposDespesa,
            'recorrencias' => $recorrencias,
            'formasPagamento' => $formasPagamento,
            'planosContas' => $planosContas,
        ]);
    }

    public function storePagar(ContaPagarStoreRequest $request)
    {
        $conta = new ContaPagarReceber($request->only('descricao', 'numero_documento', 'nota_fiscal', 'valor', 'vencimento', 'caminho_documento', 'observacoes'));
        $conta->tipo = TipoContaPagarReceberEnum::saida();
        $conta->status = StatusContaPagarEnum::make((int) $request->status);
        $conta->tipo_despesa = TipoDespesaContaPagarReceberEnum::make((int) $request->tipo_despesa);
        $conta->recorrencia = $request->recorrencia ? RecorrenciaContaPagaReceberEnum::make((int) $request->recorrencia) : null;

        if ($conta->status->isPago()) {
            $conta->valor_pago = $request->valor_pago;
            $conta->data_pagamento = $request->data_pagamento;
            $conta->forma_pagamento = FormaPagamentoContaPagarEnum::make((int) $request->forma_pagamento);
        } else {
            $conta->valor_pago = null;
            $conta->data_pagamento = null;
            $conta->forma_pagamento = null;
        }

        if ($conta->tipo_despesa->isExtra()) {
            $conta->responsavel_despesa = $request->responsavel_despesa;
        } else {
            $conta->responsavel_despesa = null;
        }

        if ($request->classificacao_conta_id) {
            $classificacao = ClassificacaoConta::find($request->classificacao_conta_id);
            $conta->classificacao()->associate($classificacao);
        }

        if ($request->caminho_documento) {
            $conta->caminho_documento = $request->caminho_documento->store('contas-pagar-receber');
        }

        $conta->save();

        return redirect()
            ->route('admin.contas-pagar-receber.index')
            ->with('status', 'Saída incluída com sucesso!');
    }

    public function storeReceber(ContaReceberStoreRequest $request)
    {
        $conta = new ContaPagarReceber($request->only('descricao', 'numero_documento', 'observacoes'));
        $conta->tipo = TipoContaPagarReceberEnum::entrada();
        $conta->status = StatusContaPagarEnum::make((int) $request->status);
        $conta->forma_recebimento = FormaPagamentoContaReceberEnum::make((int) $request->forma_recebimento);
        $conta->valor_pago = $request->valor_pago;
        $conta->valor = $request->valor_pago;               // Para conta a receber não há necessidade de controlar valor a ser pago 
        $conta->vencimento = $request->data_pagamento;      // e data de vencimento
        $conta->data_pagamento = $request->data_pagamento;
        $conta->save();

        return redirect()
            ->route('admin.contas-pagar-receber.index')
            ->with('status', 'Entrada incluída com sucesso!');
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\ContaPagarReceber  $contaPagar
     * @return \Illuminate\Http\Response
     */
    public function editPagar(ContaPagarReceber $conta)
    {
        $statuses = $this->statusSelecionaveis();
        $tiposDespesa = TipoDespesaContaPagarReceberEnum::getAll();
        $recorrencias = RecorrenciaContaPagaReceberEnum::getAll();
        $formasPagamento = FormaPagamentoContaPagarEnum::getAll();
        $planosContas = PlanoConta::all();

        return view('admin.contas-pagar-receber.edit-pagar', [
            'statuses' => $statuses,
            'tiposDespesa' => $tiposDespesa,
            'recorrencias' => $recorrencias,
            'formasPagamento' => $formasPagamento,
            'conta' => $conta,
            'planosContas' => $planosContas,
        ]);
    }

    public function updatePagar(ContaPagarUpdateRequest $request, ContaPagarReceber $conta)
    {
        $conta->fill($request->only('descricao', 'numero_documento', 'nota_fiscal', 'valor', 'vencimento', 'caminho_documento', 'observacoes'));
        $conta->tipo = TipoContaPagarReceberEnum::saida();
        $conta->status = StatusContaPagarEnum::make((int) $request->status);
        $conta->tipo_despesa = TipoDespesaContaPagarReceberEnum::make((int) $request->tipo_despesa);
        $conta->recorrencia = $request->recorrencia ? RecorrenciaContaPagaReceberEnum::make((int) $request->recorrencia) : null;

        if ($conta->status->isPago()) {
            $conta->valor_pago = $request->valor_pago;
            $conta->data_pagamento = $request->data_pagamento;
            $conta->forma_pagamento = FormaPagamentoContaPagarEnum::make((int) $request->forma_pagamento);
        } else {
            $conta->valor_pago = null;
            $conta->data_pagamento = null;
            $conta->forma_pagamento = null;
        }

        if ($conta->tipo_despesa->isExtra()) {
            $conta->responsavel_despesa = $request->responsavel_despesa;
        } else {
            $conta->responsavel_despesa = null;
        }

        if ($request->classificacao_conta_id) {
            $classificacao = ClassificacaoConta::find($request->classificacao_conta_id);
            $conta->classificacao()->associate($classificacao);
        }

        if ($request->caminho_documento) {
            Storage::delete($conta->getOriginal('caminho_documento'));
            $conta->caminho_documento = $request->caminho_documento->store('contas-pagar-receber');
        }

        $conta->save();

        return redirect()
            ->route('admin.contas-pagar-receber.index')
            ->with('status', 'Saída editada com sucesso!');
    }

    public function editReceber(ContaPagarReceber $conta)
    {
        $statuses = $this->statusSelecionaveis();
        $tiposDespesa = TipoDespesaContaPagarReceberEnum::getAll();
        $recorrencias = RecorrenciaContaPagaReceberEnum::getAll();
        $formasRecebimento = FormaPagamentoContaReceberEnum::getAll();
        $planosContas = PlanoConta::all();

        return view('admin.contas-pagar-receber.edit-receber', [
            'statuses' => $statuses,
            'tiposDespesa' => $tiposDespesa,
            'recorrencias' => $recorrencias,
            'formasRecebimento' => $formasRecebimento,
            'conta' => $conta,
            'planosContas' => $planosContas,
        ]);
    }

    public function updateReceber(ContaReceberUpdateRequest $request, ContaPagarReceber $conta)
    {
        $conta->fill($request->only('descricao', 'numero_documento', 'observacoes'));
        $conta->forma_recebimento = FormaPagamentoContaReceberEnum::make((int) $request->forma_recebimento);
        $conta->status = StatusContaPagarEnum::make((int) $request->status);
        $conta->valor_pago = $request->valor_pago;
        $conta->valor = $request->valor_pago;               // Para conta a receber não há necessidade de controlar valor a ser pago 
        $conta->vencimento = $request->data_pagamento;      // e data de vencimento
        $conta->data_pagamento = $request->data_pagamento;
        $conta->save();

        return redirect()
            ->route('admin.contas-pagar-receber.index')
            ->with('status', 'Entrada editada com sucesso!');
    }

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

        return redirect()
            ->route('admin.contas-pagar-receber.index')
            ->with('status', 'Conta excluída com sucesso!');
    }
}
