class Contabilidade::ConciliacaoBancaria < ApplicationRecord
  has_paper_trail

  belongs_to :banco, class_name: 'Base::Banco'
  belongs_to :conta_bancaria, class_name: 'Base::ContaBancaria'

  validates_presence_of :banco_id, :conta_bancaria_id, :mes_do_arquivo, :ano_do_arquivo
  validates_presence_of :arquivo_ofx, unless: Proc.new { Rails.env.test? }

  validates :ano_do_arquivo, length: {minimum: 4, maximum: 4}

  has_attached_file :arquivo_ofx
  validates_attachment_content_type :arquivo_ofx, content_type: ["text/plain", "application/octet-stream", "text/csv"]
  validates_attachment_size :arquivo_ofx, in: 0..10.megabytes, allow_nil: true

  has_attached_file :arquivo_pdf
  validates_attachment_content_type :arquivo_pdf, content_type: ["application/pdf"]
  validates_attachment_size :arquivo_pdf, in: 0..10.megabytes, allow_nil: true

  has_many :transacoes, class_name: "Contabilidade::TransacaoDaConciliacao", dependent: :destroy
  has_many :conciliacoes, through: :transacoes, class_name: 'Contabilidade::Conciliacao'

  after_create :ler_arquivo, unless: Proc.new { Rails.env.test? }
  before_destroy :valida_se_existe_item_conciliado

  enum mes_do_arquivo:{
    janeiro: 1,
    fevereiro: 2,
    marco: 3,
    abril: 4,
    maio: 5,
    junho: 6,
    julho: 7,
    agosto: 8,
    setembro: 9,
    outubro: 10,
    novembro: 11,
    dezembro: 12
  }

  def ler_arquivo
    if self.arquivo_ofx_content_type == "text/csv"
      ler_arquivo_csv
    elsif self.arquivo_ofx_content_type == "application/octet-stream" || self.arquivo_ofx_content_type == "text/plain"
      ler_arquivo_ofx
    end
  end

  def ler_arquivo_csv
    csv_text = Paperclip.io_adapters.for(self.arquivo_ofx).read.force_encoding(Encoding::UTF_8)
    csv = CSV.parse(csv_text, :headers => true)
    csv.each do |row|
      if row[1].present?
        if row[5].present?
          a, data, c, d, e, descricao, g, documento, i, j, lote, l, m, debito, o, credito, q, r, s, t, u, v, x = row[0..22]
        else
          a, data, c, d, e, f, descricao, h, i, documento, k, l, lote, n, o, debito, q, credito, s, t, u, v, x = row[0..22]
        end
        valor = debito.gsub(".","").gsub(",",".").to_d * -1 if debito.present?
        valor = credito.gsub(".","").gsub(",",".").to_d if credito.present?

        self.transacoes.create!(
          tipo: 'Deposit',
          nome: descricao,
          valor: valor.to_f,
          data: data,
          fit_id: documento,
          numero_verificador: lote,
          status: Contabilidade::TransacaoDaConciliacao.status[:pendente]
        )
      end

    end
  end

  def ler_arquivo_ofx
    begin
      file = open(self.arquivo_ofx.queued_for_write[:original].path)
      file = IO.read(file, :encoding => 'windows-1252')
      ofx = OfxParser::OfxParser.parse(file)
      ofx.bank_account.statement.transactions.each do |transacao|
        unless Contabilidade::TransacaoDaConciliacao.find_by(fit_id: transacao.fit_id).present?
          criar_transacao(transacao)
        end
      end
      raise StandardError.new "Todas as transações desse arquivo já foram lançadas" if self.transacoes.size == 0 && ofx.bank_account.statement.transactions.any?
    rescue => e
      if e.message.include?("Todas as transações desse arquivo já foram lançadas")
        errors.add(:leitura_do_arquivo, e.message)
      else
        errors.add(:leitura_do_arquivo, "Arquivo está formatado errado")
      end
      raise ActiveRecord::Rollback
    end
  end

  def criar_transacao(transacao)
    self.transacoes.create!(
      tipo: transacao.type_desc,
      nome: transacao.memo,
      valor: transacao.amount.to_f,
      data: transacao.date,
      fit_id: transacao.fit_id,
      numero_verificador: transacao.check_number,
      status: Contabilidade::TransacaoDaConciliacao.status[:pendente]
    )
  end

  def valida_se_existe_item_conciliado
    begin
      raise StandardError.new "Conciliação Não Pode Ser Excluida Pois Possui Transação Conciliada" if transacoes.any? && transacoes.conciliado.any?
    rescue => e
      errors.add(:exclusao_da_conciliacao, e.message)
      raise ActiveRecord::Rollback
    end
  end
end
