<?php
namespace Eduardokum\LaravelBoleto\Cnab\Remessa\Cnab400\Banco;

use DeepCopyTest\B;
use Eduardokum\LaravelBoleto\CalculoDV;
use Eduardokum\LaravelBoleto\Cnab\Remessa\Cnab400\AbstractRemessa;
use Eduardokum\LaravelBoleto\Contracts\Cnab\Remessa as RemessaContract;
use Eduardokum\LaravelBoleto\Contracts\Boleto\Boleto as BoletoContract;
use Eduardokum\LaravelBoleto\Util;

class Unicred extends AbstractRemessa implements RemessaContract
{
    const ESPECIE_DUPLICATA = '01';
    const ESPECIE_NOTA_PROMISSORIA = '02';
    const ESPECIE_NOTA_SEGURO = '03';
    const ESPECIE_COBRANCA_SERIADA = '04';
    const ESPECIE_RECIBO = '05';
    const ESPECIE_LETRAS_CAMBIO = '10';
    const ESPECIE_NOTA_DEBITO = '11';
    const ESPECIE_DUPLICATA_SERVICO = '12';
    const ESPECIE_OUTROS = '99';

    const OCORRENCIA_REMESSA = '01';
    const OCORRENCIA_PEDIDO_BAIXA = '02';
    const OCORRENCIA_CONCESSAO_ABATIMENTO = '04';
    const OCORRENCIA_CANC_ABATIMENTO_CONCEDIDO = '05';
    const OCORRENCIA_ALT_VENCIMENTO = '06';
    const OCORRENCIA_ALT_CONTROLE_PARTICIPANTE = '07';
    const OCORRENCIA_ALT_SEU_NUMERO = '08';
    const OCORRENCIA_PEDIDO_PROTESTO = '09';
    const OCORRENCIA_SUSTAR_PROTESTO_MANTER_CARTEIRA = '11';
    const OCORRENCIA_SUSTAR_PROTESTO_MANTER_TITULO = '19';
    const OCORRENCIA_TRANS_CESSAO_CREDITO_ID10 = '22';
    const OCORRENCIA_TRANS_CARTEIRAS = '23';
    const OCORRENCIA_DEVOLUCAO_TRANS_CARTEIRAS = '24';
    const OCORRENCIA_SUSTAR_PROTESTO_BAIXAR_TITULO = '25';
    const OCORRENCIA_PROTESTO_AUT = '26';
    const OCORRENCIA_ALT_OUTROS_DADOS = '31';
    const OCORRENCIA_DESAGENDAMENTO_DEBITO_AUT = '35';
    const OCORRENCIA_ALT_STATUS_DESCONTO = '40';
    const OCORRENCIA_ACERTO_RATEIO_CREDITO = '68';
    const OCORRENCIA_CANC_RATEIO_CREDITO = '69';


    const INSTRUCAO_SEM = '00';
    const INSTRUCAO_PROTESTAR_FAMILIAR_XX = '05';
    const INSTRUCAO_PROTESTAR_XX = '06';
    const INSTRUCAO_NAO_COBRAR_JUROS = '08';
    const INSTRUCAO_NAO_RECEBER_APOS_VENC = '09';
    const INSTRUCAO_MULTA_10_APOS_VENC_4 = '10';
    const INSTRUCAO_NAO_RECEBER_APOS_VENC_8 = '11';
    const INSTRUCAO_COBRAR_ENCAR_APOS_5 = '12';
    const INSTRUCAO_COBRAR_ENCAR_APOS_10 = '13';
    const INSTRUCAO_COBRAR_ENCAR_APOS_15 = '14';
    const INSTRUCAO_CENCEDER_DESC_APOS_VENC = '15';
    const INSTRUCAO_DEVOLVER_XX = '18';

    public function __construct(array $params = [])
    {
        parent::__construct($params);
        $this->addCampoObrigatorio('idremessa');
    }


    /**
     * Código do banco
     *
     * @var string
     */
    protected $codigoBanco = BoletoContract::COD_BANCO_UNICRED;

    /**
     * Define as carteiras disponíveis para cada banco
     *
     * @var array
     */

    protected $carteiras = ['04', '09', '21', '28'];

    /**
     * Caracter de fim de linha
     *
     * @var string
     */
    protected $fimLinha = "\r\n";

    /**
     * Caracter de fim de arquivo
     *
     * @var null
     */
    protected $fimArquivo = "\r\n";

    /**
     * Codigo do cliente junto ao banco.
     *
     * @var string
     */
    protected $codigoCliente;

    /**
     * Retorna o codigo do cliente.
     *
     * @return mixed
     * @throws \Exception
     */
    public function getCodigoCliente()
    {
        if (empty($this->codigoCliente)) {
            $this->codigoCliente = Util::formatCnab('9', $this->getCarteiraNumero(), 4) .
            Util::formatCnab('9', $this->getAgencia(), 5) .
            Util::formatCnab('9', $this->getConta(), 7) .
            Util::formatCnab('9', $this->getContaDv() ?: CalculoDV::bradescoContaCorrente($this->getConta()), 1);
        }

        return $this->codigoCliente;
    }

    /**
     * Seta o codigo do cliente.
     *
     * @param mixed $codigoCliente
     *
     * @return Bradesco
     */
    public function setCodigoCliente($codigoCliente)
    {
        $this->codigoCliente = $codigoCliente;

        return $this;
    }

    /**
     * @return $this
     * @throws \Exception
     */
    protected function header()
    {
        $this->iniciaHeader();

        $this->add(1, 1, '0');
        $this->add(2, 2, '1');
        $this->add(3, 9, 'REMESSA');
        $this->add(10, 11, '01');
        $this->add(12, 26, Util::formatCnab('X', 'COBRANCA', 15));
        $this->add(27, 46, Util::formatCnab('9', $this->getCodigoCliente(), 20));
        $this->add(47, 76, Util::formatCnab('X', $this->getBeneficiario()->getNome(), 30));
        $this->add(77, 79, $this->getCodigoBanco());
        $this->add(80, 94, Util::formatCnab('X', 'UNICRED', 15));
        $this->add(95, 100, $this->getDataRemessa('dmy'));
        $this->add(101, 107, '');
        $this->add(108, 110, '000');
        $this->add(111, 117, Util::formatCnab('9', $this->getIdremessa(), 7));
        $this->add(118, 394, '');
        $this->add(395, 400, Util::formatCnab('9', 1, 6));

        return $this;
    }

    /**
     * @param BoletoContract $boleto
     *
     * @return $this
     * @throws \Exception
     */
    public function addBoleto(BoletoContract $boleto)
    {
        $this->boletos[] = $boleto;
        $this->iniciaDetalhe();

        $this->add(1, 1, '1');
        $this->add(2, 6, Util::formatCnab('9', $this->getAgencia(), 5));
        $this->add(7, 7, Util::formatCnab('X', $boleto->getAgenciaDv(), 1));
        $this->add(8, 19, Util::formatCnab('9', $this->getConta(), 12));
        $this->add(20, 20, Util::formatCnab('X', $this->getContaDv(), 1));
        $this->add(21, 21, '0');
        $this->add(22, 24, Util::formatCnab('9', '21', 3));
        $this->add(25, 37, Util::formatCnab('9', '0', 13));
        $this->add(38, 62, Util::formatCnab('X', '', 25));
        $this->add(63, 65, '136');
        $this->add(66, 67, '00');
        $this->add(68, 92, Util::formatCnab('X', '', 25));
        $this->add(93, 93, '0');
        $this->add(94, 94, Util::formatCnab('X', $boleto->getMulta() > 0 ? '2' : '3', 1));
        $this->add(95, 104, Util::formatCnab('9', $boleto->getMulta() > 0 ? $boleto->getMulta() : '0', 10, 2));
        $this->add(105, 105, Util::formatCnab('X', $boleto->getMoraTipo(), 1));
        $this->add(106, 106, 'N');
        $this->add(107, 107, 'N');
        $this->add(108, 108, '');
        $this->add(109, 110, self::OCORRENCIA_REMESSA); // REGISTRO 01
        $flag_ocorrencia = self::OCORRENCIA_REMESSA;
        if ($boleto->getStatus() == $boleto::STATUS_BAIXA) {
            $flag_ocorrencia = self::OCORRENCIA_PEDIDO_BAIXA;
            $this->add(109, 110, self::OCORRENCIA_PEDIDO_BAIXA); // BAIXA 02
        }
        else if ($boleto->getStatus() == $boleto::STATUS_ALTERACAO) {
            $flag_ocorrencia = self::OCORRENCIA_ALT_VENCIMENTO;
            $this->add(109, 110, self::OCORRENCIA_ALT_VENCIMENTO); // ALTERAR VENCIMENTO 06
        }
        else if ($boleto->getStatus() == $boleto::STATUS_ALTERACAO_DATA) {
            $flag_ocorrencia = self::OCORRENCIA_ALT_VENCIMENTO;
            $this->add(109, 110, self::OCORRENCIA_ALT_VENCIMENTO);
        }
        else if ($boleto->getStatus() == $boleto::STATUS_PROTESTO_AUTOMATICO){
            $flag_ocorrencia = self::OCORRENCIA_PROTESTO_AUT;
            $this->add(109, 110, self::OCORRENCIA_PROTESTO_AUT);
        }
        else if ($boleto->getStatus() == $boleto::STATUS_CUSTOM) {
            $flag_ocorrencia = sprintf('%2.02s', $boleto->getComando());
            $this->add(109, 110, sprintf('%2.02s', $boleto->getComando()));
        }
        $this->add(111, 120, Util::formatCnab('X', $boleto->getNumeroDocumento(), 10));
        $this->add(121, 126, $boleto->getDataVencimento()->format('dmy'));
        $this->add(127, 139, Util::formatCnab('9', $boleto->getValor(), 13, 2));
        $this->add(140, 149, Util::formatCnab('9', '0', 10));
        $this->add(150, 150, Util::formatCnab('X', $boleto->getDesconto() > 0 ? '1' : '0', 1));
        $this->add(151, 156, $boleto->getDataDocumento()->format('dmy'));
        $this->add(157, 157, '0');
        $this->add(158, 158, '3');
        $this->add(159, 160, self::INSTRUCAO_SEM);
        if($boleto->getDiasProtesto() == 0){
            $this->add(158, 158, '3');
            $this->add(159, 160, Util::formatCnab('9', $boleto->getDiasProtesto(), 2));
        } else {
            $this->add(158, 158, '1');
            if($flag_ocorrencia == (self::OCORRENCIA_REMESSA || self::OCORRENCIA_PROTESTO_AUT)){
                $this->add(159, 160, Util::formatCnab('9', $boleto->getDiasProtesto(), 2));
            }
        }
        $this->add(161, 173, Util::formatCnab('9', $boleto->getMoraDia(), 13, 2));
        $this->add(174, 179, $boleto->getDesconto() > 0 ? $boleto->getDataDesconto()->format('dmy') : '000000');
        $this->add(180, 192, Util::formatCnab('9', $boleto->getDesconto() > 0 ? $boleto->getDesconto() : Util::formatCnab('9', '0', 13), 13, 2));
        $this->add(193, 203, Util::formatCnab('9', $boleto->getNossoNumero($this->getEmpresa()), 11));
        $this->add(204, 205, '00');
//        if($boleto->getStatus() == $boleto::STATUS_CUSTOM){
//            $this->add(206, 218, Util::formatCnab('9', $this->getValorAbatimento(), 13, 2));
//        }else {
            $this->add(206, 218, Util::formatCnab('9', 0, 13, 2));
//        }
        $this->add(219, 220, strlen(Util::onlyNumbers($boleto->getPagador()->getDocumento())) == 14 ? '02' : '01');
        $this->add(221, 234, Util::formatCnab('9', Util::onlyNumbers($boleto->getPagador()->getDocumento()), 14));
        $this->add(235, 274, Util::formatCnab('X', $boleto->getPagador()->getNome(), 40));
        $this->add(275, 314, Util::formatCnab('X', $boleto->getPagador()->getEndereco(), 40));
        $this->add(315, 326, Util::formatCnab('X', $boleto->getPagador()->getBairro(), 12));
        $this->add(327, 334, Util::formatCnab('9', Util::onlyNumbers($boleto->getPagador()->getCep()), 8));
        $this->add(335, 354, Util::formatCnab('X', $boleto->getPagador()->getCidade(), 20));
        $this->add(355, 356, Util::formatCnab('9', $boleto->getPagador()->getUf(), 2));
        $this->add(357, 394, Util::formatCnab('X', '', 38));
        $this->add(395, 400, Util::formatCnab('9', $this->iRegistros + 1, 6));

        return $this;
    }

    /**
     * @return $this
     * @throws \Exception
     */
    protected function trailer()
    {
        $this->iniciaTrailer();

        $this->add(1, 1, '9');
        $this->add(2, 394, '');
        $this->add(395, 400, Util::formatCnab('9', $this->getCount(), 6));

        return $this;
    }
}
