class AgentImportFile < ApplicationRecord
  include Statesman::Adapters::ActiveRecordQueries[
    transition_class: AgentImportFileTransition,
    initial_state: AgentImportFileStateMachine.initial_state
  ]
  include ImportFile
  default_scope { order("agent_import_files.id DESC") }
  scope :not_imported, -> { in_state(:pending) }
  scope :stucked, -> { in_state(:pending).where("agent_import_files.created_at < ?", 1.hour.ago) }

  has_one_attached :attachment
  belongs_to :user
  has_many :agent_import_results, dependent: :destroy

  has_many :agent_import_file_transitions, autosave: false, dependent: :destroy

  attr_accessor :mode

  def state_machine
    AgentImportFileStateMachine.new(self, transition_class: AgentImportFileTransition)
  end

  delegate :can_transition_to?, :transition_to!, :transition_to, :current_state,
    to: :state_machine

  def import_start
    case edit_mode
    when "create"
      import
    when "update"
      modify
    when "destroy"
      remove
    else
      import
    end
  end

  def import
    transition_to!(:started)
    num = { agent_imported: 0, user_imported: 0, failed: 0 }
    rows = open_import_file
    field = rows.first
    row_num = 1
    if [ field["first_name"], field["last_name"], field["full_name"] ].reject { |field| field.to_s.strip == "" }.empty?
      raise "You should specify first_name, last_name or full_name in the first line"
    end

    # rows.shift

    AgentImportResult.create!(agent_import_file_id: id, body: rows.headers.join("\t"))
    rows.each do |row|
      row_num += 1
      import_result = AgentImportResult.create!(agent_import_file_id: id, body: row.fields.join("\t"))
      next if row["dummy"].to_s.strip.present?

      agent = Agent.new
      agent = set_agent_value(agent, row)

      if agent.save!
        import_result.agent = agent
        num[:agent_imported] += 1
      end

      import_result.save!
    end
    Sunspot.commit
    rows.close
    transition_to!(:completed)
    mailer = AgentImportMailer.completed(self)
    send_message(mailer)
    num
  rescue StandardError => e
    self.error_message = "line #{row_num}: #{e.message}"
    transition_to!(:failed)
    mailer = AgentImportMailer.failed(self)
    send_message(mailer)
    raise e
  end

  def self.import
    AgentImportFile.not_imported.each do |file|
      file.import_start
    end
  rescue StandardError
    Rails.logger.info "#{Time.zone.now} importing agents failed!"
  end

  def modify
    transition_to!(:started)
    rows = open_import_file
    rows.shift
    row_num = 1

    rows.each do |row|
      row_num += 1
      next if row["dummy"].to_s.strip.present?

      agent = Agent.find_by(id: row["id"])
      next unless agent

      agent.full_name = row["full_name"] if row["full_name"].to_s.strip.present?
      agent.full_name_transcription = row["full_name_transcription"] if row["full_name_transcription"].to_s.strip.present?
      agent.first_name = row["first_name"] if row["first_name"].to_s.strip.present?
      agent.first_name_transcription = row["first_name_transcription"] if row["first_name_transcription"].to_s.strip.present?
      agent.middle_name = row["middle_name"] if row["middle_name"].to_s.strip.present?
      agent.middle_name_transcription = row["middle_name_transcription"] if row["middle_name_transcription"].to_s.strip.present?
      agent.last_name = row["last_name"] if row["last_name"].to_s.strip.present?
      agent.last_name_transcription = row["last_name_transcription"] if row["last_name_transcription"].to_s.strip.present?
      agent.address_1 = row["address_1"] if row["address_1"].to_s.strip.present?
      agent.address_2 = row["address_2"] if row["address_2"].to_s.strip.present?
      agent.save!
    end
    transition_to!(:completed)
    mailer = AgentImportMailer.completed(self)
    send_message(mailer)
  rescue StandardError => e
    self.error_message = "line #{row_num}: #{e.message}"
    transition_to!(:failed)
    mailer = AgentImportMailer.failed(self)
    send_message(mailer)
    raise e
  end

  def remove
    transition_to!(:started)
    rows = open_import_file
    rows.shift
    row_num = 1

    rows.each do |row|
      row_num += 1
      next if row["dummy"].to_s.strip.present?

      agent = Agent.find_by(id: row["id"].to_s.strip)
      next unless agent

      agent.picture_files.destroy_all
      agent.reload
      agent.destroy
    end
    transition_to!(:completed)
    mailer = AgentImportMailer.completed(self)
    send_message(mailer)
  rescue StandardError => e
    self.error_message = "line #{row_num}: #{e.message}"
    transition_to!(:failed)
    mailer = AgentImportMailer.failed(self)
    send_message(mailer)
    raise e
  end

  private

  def open_import_file
    tempfile = Tempfile.new(self.class.name.underscore)
    tempfile.puts(convert_encoding(attachment.download))
    tempfile.close

    file = CSV.open(tempfile, col_sep: "\t")
    header = file.first
    rows = CSV.open(tempfile, headers: header, col_sep: "\t")
    tempfile.close(true)
    file.close
    rows
  end

  def set_agent_value(agent, row)
    agent.first_name = row["first_name"] if row["first_name"]
    agent.middle_name = row["middle_name"] if row["middle_name"]
    agent.last_name = row["last_name"] if row["last_name"]
    agent.first_name_transcription = row["first_name_transcription"] if row["first_name_transcription"]
    agent.middle_name_transcription = row["middle_name_transcription"] if row["middle_name_transcription"]
    agent.last_name_transcription = row["last_name_transcription"] if row["last_name_transcription"]

    agent.full_name = row["full_name"] if row["full_name"]
    agent.full_name_transcription = row["full_name_transcription"] if row["full_name_transcription"]

    agent.address_1 = row["address_1"] if row["address_1"]
    agent.address_2 = row["address_2"] if row["address_2"]
    agent.zip_code_1 = row["zip_code_1"] if row["zip_code_1"]
    agent.zip_code_2 = row["zip_code_2"] if row["zip_code_2"]
    agent.telephone_number_1 = row["telephone_number_1"] if row["telephone_number_1"]
    agent.telephone_number_2 = row["telephone_number_2"] if row["telephone_number_2"]
    agent.fax_number_1 = row["fax_number_1"] if row["fax_number_1"]
    agent.fax_number_2 = row["fax_number_2"] if row["fax_number_2"]
    agent.note = row["note"] if row["note"]
    agent.birth_date = row["birth_date"] if row["birth_date"]
    agent.death_date = row["death_date"] if row["death_date"]

    # if row['username'].to_s.strip.blank?
    agent.email = row["email"].to_s.strip
    agent.required_role = Role.find_by(name: row["required_role"].to_s.strip.camelize) || Role.find_by(name: "Guest")
    # else
    #   agent.required_role = Role.where(name: row['required_role'].to_s.strip.camelize).first || Role.where('Librarian').first
    # end
    language = Language.find_by(name: row["language"].to_s.strip.camelize) || Language.find_by(iso_639_2: row["language"].to_s.strip.downcase) || Language.find_by(iso_639_1: row["language"].to_s.strip.downcase)
    agent.language = language if language
    country = Country.find_by(name: row["country"].to_s.strip)
    agent.country = country if country
    agent
  end
end

# == Schema Information
#
# Table name: agent_import_files
#
#  id                       :bigint           not null, primary key
#  agent_import_fingerprint :string
#  edit_mode                :string
#  error_message            :text
#  executed_at              :datetime
#  note                     :text
#  user_encoding            :string
#  created_at               :datetime         not null
#  updated_at               :datetime         not null
#  parent_id                :bigint
#  user_id                  :bigint           not null
#
# Indexes
#
#  index_agent_import_files_on_parent_id  (parent_id)
#  index_agent_import_files_on_user_id    (user_id)
#
# Foreign Keys
#
#  fk_rails_...  (user_id => users.id)
#
