class Admins::ImportHackService < ApplicationService
  Error = Class.new(StandardError)

  attr_reader :file, :result

  def initialize(file, sub_discipline_id)
    @sub_discipline_id = sub_discipline_id
    @file   = file
    @result = { success: 0, fail: [] }
  end

  def call
    raise Error, '文件不存在' if file.blank?

    excel = Admins::ImportHackExcel.new(file)
    excel.read_each(&method(:save_data))

    result
  rescue ApplicationImport::Error => ex
    raise Error, ex.message
  end

  private

  def save_data(data)
    count = 0
    unless data.task_name.to_s.strip.present?
      return
    end

    unless data.login.to_s.strip.present?
      raise '用户名不能为空'
    end

    user = User.find_by(login: data.login.to_s.strip)
    hack = Hack.new(name: data.task_name, difficult: data.difficulty || 1, user_id: user.id, status: 1,
                    time_limit: data.time, description: data.desc, score: 200, sub_discipline_id: @sub_discipline_id)
    hack.identifier = ApplicationController.new.generate_identifier Hack, 8
    ActiveRecord::Base.transaction do
      hack.save!
      hack_set(hack, data)
      hack.hack_codes.create!(code: Base64.urlsafe_encode64s(data.code), language: data.language, modify_time: Time.now)

      ItemBank.create!(public: true, name: data.task_name, container: hack, item_type: 'PROGRAM', difficulty: data.difficulty || 1, user_id: user.id, sub_discipline_id: @sub_discipline_id)
      count += 1
    end

    result[:success] += count
  rescue Exception => ex
    fail_data = data.as_json
    fail_data[:data] = fail_data.values.join(',')
    fail_data[:message] = ex.message

    result[:fail] << fail_data
  end


  def hack_set(hack, data)
    (1..4).each do |d|
      set_in = data.send("set_input#{d}").to_s.strip
      set_out = data.send("set_output#{d}").to_s.strip
      if set_in.present? && set_out.present?
        hack.hack_sets.create!(input: set_in, output: set_out, position: d )
      end
    end
  end
end