class PDocument < ApplicationRecord
  belongs_to :p_document_type
  has_many :p_sheet_lines, :dependent => :destroy
  belongs_to :p_customer
  belongs_to :p_payment_type
  belongs_to :p_customer_sheet
  belongs_to :p_sheet_line
  
  belongs_to :particular_bill, :class_name => "Particular"
  belongs_to :particular_send, :class_name => "Particular"
  
  belongs_to :p_ship_tour_truck
  
  has_many :p_payment_documents, :dependent => :destroy
  has_many :p_payments, :through => :p_payment_documents
  has_many :relative_docs, :class_name => "PDocument", :foreign_key => :doc_ref_id
  
  has_one :p_compta_element, :as => :element, :dependent => :destroy
  
  belongs_to :element, :polymorphic => true
  
  validates :d_number, :uniqueness => true
  
  accepts_nested_attributes_for :p_sheet_lines, allow_destroy: true
  
  
  attr_accessor :sheet_id, :skip_update_caches
  include Rails.application.routes.url_helpers
  
  after_initialize do
    
    if self.element and self.element_type == "PCustomerSheet" and !self.id

      self.cust_ref = self.element.cust_ref
      
      self.comptant = self.element.comptant 
      
      self.acompte = self.element.acompte
      self.acompte_percent  = self.element.acompte_percent 
      
      self.payment_delais = self.element.payment_delais
      
      self.payment_fin_de_mois= self.element.payment_fin_de_mois
      
      self.p_payment_type_id= self.element.p_payment_type_id
      
    end
  end
  
  
  after_save do
    if !skip_update_caches
      self.generate_p_compta_element
      self.p_customer.update_caches if self.p_customer
    end
    
  end
  
  def self.update_arrondi
    PDocument.where("paid = 0 and cache_to_paid >= -1.0 and cache_to_paid <= 1.0").all.each do |p_doc|
      puts "IDDDDDD"
      puts p_doc.id
      p_doc.save
    end
  end
  
  def arrondi
    self.p_payment_documents.joins(:p_payment).where(:p_payments => {:p_payment_type_id => 10}).first
  end
  
  def last_paid
    self.p_payments.order("paid_at DESC").first
  end
  before_save do
    puts self.label
    self.echeance_date = self.echeance
    
    if self.label == "Facture" or self.label == "Avoir"
      #fdssdfdf = dfsd
      self.cache_total_ht = self.totals[:ok_total]
      self.cache_total_ttc = self.totals[:ok_total_ttc]
      self.cache_total_tva = self.totals[:ok_total_ttc] - self.totals[:ok_total]
      self.cache_tva = (self.p_sheet_lines.first.tva*100) if self.p_sheet_lines.first
      
      #arrondis
      
      set_arrondis()
      
      
      self.cache_to_paid = self.total_du
      
      
      self.cache_to_th_paid = self.totals[:ok_total_ttc] - total_paid_th - total_paid
      
      
      
    else
      self.cache_total_ht = self.totals[:total]
      self.cache_total_ttc = self.totals[:total_ttc]
      self.cache_total_tva = self.totals[:total_ttc] - self.totals[:total]
      self.cache_tva = (self.p_sheet_lines.first.tva*100) if self.p_sheet_lines.first
    end
  end
  
  def set_arrondis
    if self.total_du != 0.0 and self.total_du >= -1.0 and self.total_du <= 1.0
      #On fait un arrondi mec !
      
      if self.total_du_without_arrondi != 0.0 and self.total_du_without_arrondi >= -1.0 and self.total_du_without_arrondi <= 1.0
        arrondi_amount = self.total_du_without_arrondi
        if last_paid and arrondi_date = last_paid.paid_at
        else
          arrondi_date = Time.now
        end
        
        if self.arrondi
          arr = self.arrondi
          arr.amount = arrondi_amount
          arr.skip_validation = true
          #arr.save
          arr.p_payment.amount = arrondi_amount
          arr.p_payment.paid_at = arrondi_date
          #arr.p_payment.save
          
          
        else
          arr = self.p_payments.new(:p_customer_id => self.p_customer_id, :amount => arrondi_amount, :paid => true, :paid_at => arrondi_date, :p_payment_type_id => 10)
          arr.p_payment_documents << PPaymentDocument.new(:p_document => self, :amount => arrondi_amount, :skip_validation => true)
          arr.save
          #puts arr.errors.messages
          #dqsdqsqs = dsqqds
        end
          
      
      else
        self.arrondi.p_payment.destroy if self.arrondi
      end
    elsif self.total_du != 0.0
      self.arrondi.p_payment.destroy if self.arrondi
    end
    true
  
  end
  
  before_create do
    archive_particulars
    
  end
  
  
  after_create do
    generate_number
    archive_sheet_line if self.p_document_type.label != "Avoir"
    
  
    
    
    if self.element and self.element_type == "PCustomerSheet" and self.p_document_type.label == "Facture"
      
      self.element.p_sheet_lines.each do |p_sheet_line|
        
        p_sheet_line.p_payments.order("paid_at ASC, theo_date ASC").each do |p_payment|
          p_payment.auto_affect(self)
          
          self.save
          
        end
        
        
      end
      
      
      
    end
    
    
    
    if self.element and self.element_type == "PCustomerSheet" and self.p_document_type.label == "Avoir"
      self.element.state = "remboursée"
      self.element.save
    end
    
    
    self.update_paid_status()
    
    
  end
  
  
  before_validation do
    
    
    if !self.id and self.element and self.element_type == "PCustomerSheet"
      self.p_commercial_id = self.element.p_commercial_id
      
    end
    
    
    
    t = PDocument.where(:doc_ref_id => self.doc_ref_id)
    if self.id 
      t= t.where("id != ?", self.id)
    end
    if self.label == "Avoir" and (!self.id and t.first)
     # errors.add(:acompte, "Avoir déjà créé") 
    end
    
    
    if self.comptant
      
      if self.acompte
        errors.add(:acompte, "N'est pas compatible avec les paiements comptants") 
        
      end
      
      if self.acompte_percent?
        errors.add(:acompte_percent, "N'est pas compatible avec les paiements comptants") 
        
      end
      
      if self.payment_delais?
        errors.add(:payment_delais, "N'est pas compatible avec les paiements comptants") 
        
      end
      
      if self.payment_fin_de_mois
        errors.add(:payment_fin_de_mois, "N'est pas compatible avec les paiements comptants") 
        
      end

    end
    
    if self.acompte
      if !self.acompte_percent?
        errors.add(:acompte_percent, "Doit être remplis pour demander un acompte") 
      end
    end
    
    
    if !self.comptant
      if !self.payment_delais?
        errors.add(:payment_delais, "Délais de paiement nécessaire si pas de paiement comptant") 
      end
    end
    
    
    if self.p_document_type
      self.label = self.p_document_type.label.to_s
    end
    
    if self.sheet_id
      self.p_sheet_line_id = self.sheet_id
    end
    
    if self.id and self.label == "Facture"
      self.paid_completed?
      self.th_paid_completed?
    end
    
    
    
    if self.element_type == "PCustomerSheet"
      self.p_customer = self.element.p_customer
    end
    
    self.verify
    if !self.id
      
      if self.p_document_type.label == "Facture" #or self.p_document_type.label == "Bon de livraison"
        if PDocument.where(:element_id => self.element_id, :element_type => self.element_type,:p_document_type_id => self.p_document_type_id).count > 0
          if self.element_type == "PCustomerSheet" and self.element and self.element.state != "remboursée"

            errors.add(:element_id, 'Le document existe déjà')
          end
        end
      end
    end
  end
  
  
  def generate_p_compta_element
    if self.id and self.p_document_type_id == 4 or self.p_document_type_id == 7
      if p_compta_element = PComptaElement.where(:element_type => "PDocument", :element_id => self.id).first
        
      else
        p_compta_element = PComptaElement.new(:p_customer => self.p_customer, :element => self)
      end
    
      p_compta_element.amount = (self.cache_total_ttc * -1.00)
      p_compta_element.date = self.created_at
    
      p_compta_element.save
    end
  end
  
  def update_paid_status
    if self.label == "Facture"
      self.paid_completed?
      self.th_paid_completed?
      self.save
    end
  end
  
  def archive_particulars
    if !self.particular_bill and self.element_type == "PCustomerSheet" and self.element.particular_bill
      self.particular_bill = self.element.particular_bill.dup
      self.particular_bill.owner = nil
      self.element.particular_bill.p_contacts.each do |pc|
        self.particular_bill.p_contacts << pc.dup
      end
    end
    
    if !self.particular_send and self.element_type == "PCustomerSheet" and self.element.particular_send
      self.particular_send = self.element.particular_send.dup
      self.particular_send.owner = nil
      self.element.particular_send.p_contacts.each do |pc|
        self.particular_send.p_contacts << pc.dup
      end
      
    end
  end
  
  def archive_sheet_line
    if self.element_type == "PCustomerSheet"
      
      if self.p_document_type.label == "Bon de livraison"
      
        if self.sheet_id
          self.element.p_sheet_lines.where(:cancel => false).where(:id => self.sheet_id).each do |p_sheet_line|
            n_sheet_line = p_sheet_line.dup
            n_sheet_line.p_customer_sheet = nil
            n_sheet_line.p_document = self
            self.p_sheet_lines << n_sheet_line
        
            self.save
          end
        else
          self.element.p_sheet_lines.where(:cancel => false).joins(:p_product).where("'lock' IS NULL OR (p_products.p_product_cat_id != 6 OR (p_products.p_product_cat_id = 6 and externe = 1))").each do |p_sheet_line|
          
          
            n_sheet_line = p_sheet_line.dup
            n_sheet_line.p_customer_sheet = nil
            n_sheet_line.p_document = self
            self.p_sheet_lines << n_sheet_line
        
            self.save
            p_sheet_line.bl = true
            p_sheet_line.save
          end
        
        end
      else
        self.element.p_sheet_lines.where(:cancel => false).joins(:p_product).each do |p_sheet_line|
        
        
          n_sheet_line = p_sheet_line.dup
          n_sheet_line.p_customer_sheet = nil
          n_sheet_line.p_document = self
          self.p_sheet_lines << n_sheet_line
      
          self.save
        end
        
      end
    end
  end
  
  def generate_number

    
    if !self.d_number
      
      self.d_year = self.element.document_date(self).year
      

      self.d_prefix = self.p_document_type.prefix.to_s
      self.label = self.p_document_type.label.to_s
      self.header = self.p_document_type.header.to_s
      self.footer = self.p_document_type.footer.to_s
      self.image_file_id = self.p_document_type.image_file_id
      self.data_file_id = self.p_document_type.data_file_id

      self.name = self.p_document_type.name
      
      last_number = 0
      last_dt = PDocument.where("d_number is not null").where(:d_year => self.d_year,:p_document_type_id => self.p_document_type_id).order("d_index DESC").first

      last_number = last_dt.d_index if last_dt
      
      self.d_index = last_number+1
      self.d_number = self.d_prefix+self.d_year.to_s+('%05d' % self.d_index)
      self.save
      
     
    end
  end
	def verify(size=16)
		if !self.token
			s = ""
			size.times { s << (i = Kernel.rand(62); i += ((i < 10) ? 48 : ((i < 36) ? 55 : 61 ))).chr }
			self.token = s
    end
  end
  
  def name_for_payment
    
    self.created_at.strftime("%d/%m/%Y")+" - "+self.d_number.to_s+" - "+ActionController::Base.helpers.number_to_currency(self.cache_total_ttc)+"("+ActionController::Base.helpers.number_to_currency(self.cache_to_th_paid)+")"
  end
  
  def totals
    PSheetLine.totals(self.p_sheet_lines)
  end
  
  def total_paid
    self.p_payment_documents.joins(:p_payment).where(:p_payments => {:paid => true, :canceled => false}).sum(:amount)
  end
  
  def total_paid_without_arrondi
    self.p_payment_documents.joins(:p_payment).where(:p_payments => {:paid => true, :canceled => false}).where("p_payments.p_payment_type_id != ?",10).sum(:amount)
  end
  
  def total_paid_at
    
  end
  
  def total_paid_th
    self.p_payment_documents.joins(:p_payment).where(:p_payments => {:paid => false, :canceled => false}).sum(:amount)
    
  end
  
  def total_paid_th_at
    
  end
  
  def total_du_at
    
  end
  
  def total_du_th_at
    
  end
  
  def total_du_without_arrondi
    self.totals[:ok_total_ttc].to_f - self.total_paid_without_arrondi
  end
  
  def total_du
    self.totals[:ok_total_ttc].to_f - self.total_paid.to_f
  end
  
  def total_du_th
    self.totals[:ok_total_ttc].to_f - self.total_paid_th.to_f
  end
  
  def th_paid_completed?
    
    if self.total_paid_th + self.total_paid == self.totals[:ok_total_ttc].to_f
      self.theo_paid = true
    else
      self.theo_paid = false
    end
  end
  
  def paid_completed?
    if self.total_paid.to_f == self.totals[:ok_total_ttc].to_f
      self.paid = true
      self.paid_at = self.last_paid.paid_at if self.last_paid
    else
      self.paid = false
      self.paid_at = nil
    end
  end
  
  
  def echeance
    if self.id
      d = self.created_at
    else
      d = Time.now
    end
    if self.comptant or self.label == "Avoir"
      d
    else
      d + self.payment_delais.to_i.day
    end
  end
  
  
  def generate_pdf
    
    
    @element = self.element
    
    doc_number = self.d_number
    url = admin_p_document_path(:id => self.token, :html => true)
    
    if self and self.d_prefix == "BL"
      @bl = true
    end
  
    
    
    @temp_file = "#{Rails.root}/pdf/p_documents/#{doc_number}_temp.pdf"
    @final_file = "#{Rails.root}/pdf/p_documents/#{doc_number}_temp2.pdf"
    @final_file2 = "#{Rails.root}/pdf/p_documents/#{doc_number}.pdf"
    
    url = (Rails.env.development? ? "http://localhost:4000" : "http://3p.quartz.xyz").to_s+url
    puts url
    pdf = (((@bl and self and self.p_sheet_line) ) ? "pdf2" : "pdf")
    
    if !@bl or (self and !self.p_sheet_line)
      node_file = @temp_file
    else
      node_file = @final_file2
      
    end
    
    system("node #{pdf}.js #{Shellwords.escape(url)} #{Shellwords.escape(@temp_file)}")
  
    
      
    require 'posix/spawn'
    
    if !@bl or (self and !self.p_sheet_line)
      if self.p_document_type.data_file 
        ::POSIX::Spawn::Child.new 'pdftk', @temp_file, 'background', self.p_document_type.data_file.file.path, 'output',  @final_file

      else
        ::POSIX::Spawn::Child.new 'pdftk', @temp_file, 'stamp', "#{Rails.root}/pdf_stamp/en-tete.pdf", 'output',  @final_file
      
      end

      
      ::POSIX::Spawn::Child.new 'pdftk', @final_file,"#{Rails.root}/pdf_stamp/cgv.pdf",  'cat', 'output',  @final_file2  #AJOUT CGV 
      
      
    else
      File.rename(@temp_file, @final_file2)
      
    end
    File.delete(@temp_file) if File.exist?(@temp_file)
    File.delete(@final_file) if File.exist?(@final_file)
    
    return @final_file2
    
    
    
  end
  
  def create_avoir
    p_document = self
   
    avoir = PDocument.new(:created_at => self.created_at, :label => "Avoir", :doc_ref_id => self.id, :doc_ref_number => self.d_number, :p_document_type => PDocumentType.find_by_label("Avoir"), :element_type => self.element_type, :element_id => self.element_id, :p_customer_id => self.p_customer_id, :particular_bill_id => self.particular_bill_id,  :particular_send_id => self.particular_send_id)
   
    
    self.p_sheet_lines.each do |p_sheet_line|
      new_psl = p_sheet_line.dup
      
      new_psl.qte = (new_psl.qte*-1)
      new_psl.ok_qte = (new_psl.ok_qte*-1)
      new_psl.imported = false
      new_psl.arrondi = false
      puts new_psl.ok_qte
      
      #dgfgdf = fdfg
      
      avoir.p_sheet_lines << new_psl
      
    end
  
   
   
   
    return avoir
    
    #if avoir.element and avoir.element_type == "PCustomerSheet"
    #  avoir.element.state = "remboursée"
    #  avoir.element.save
    #end
    
    
    ######
    
   
    
    
    
  end
  
  
  
  
  
  
  
end