#coding=utf-8
#
#  文件上传
class AttachmentsController < ApplicationController
  before_action :require_login, :check_auth, except: [:show]
  before_action :find_file, only: %i[show destroy]
  before_action :attachment_candown, only: [:show]

  include ApplicationHelper

  def show
    # 1. 优先跳到cdn
    # 2. 如果没有cdn，send_file
    if @file.cloud_url.present?
      update_downloads(@file)
      redirect_to @file.cloud_url and return
    end

    pdf_attachment = params[:disposition] || "attachment"
    if pdf_attachment == "inline"
      send_file absolute_path(local_path(@file)),filename: @file.filename, disposition: 'inline',type: 'application/pdf'
    else
      send_file(absolute_path(local_path(@file)), filename: @file.filename,stream:false, type: @file.content_type.presence || 'application/octet-stream')
    end
    update_downloads(@file)
  end

  def create
    # 1. 本地存储
    # 2. 上传到云
    upload_file = params["file"] || params["#{params[:file_param_name]}"] # 这里的file_param_name是为了方便其他插件名称
    uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
    raise "未上传文件" unless upload_file

    folder = edu_setting('attachment_folder')
    raise "存储目录未定义" unless folder.present?

    month_folder = current_month_folder
    save_path = File.join(folder, month_folder)

    ext = file_ext(upload_file.original_filename)

    local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)

    content_type = upload_file.content_type.presence || 'application/octet-stream'

    # remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
    remote_path = nil # TODO 暂时本地上传，待域名配置后方可上传至云端

    logger.info "local_path: #{local_path}"
    logger.info "remote_path: #{remote_path}"


    disk_filename = local_path[save_path.size + 1, local_path.size]
    #存数据库
    #
    @attachment = Attachment.where(disk_filename: disk_filename,
                                   author_id: current_user.id,
                                   cloud_url: remote_path).first

    if @attachment.blank?
      @attachment = Attachment.new
      @attachment.filename = upload_file.original_filename
      @attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
      @attachment.filesize = upload_file.tempfile.size
      @attachment.content_type = content_type
      @attachment.digest = digest
      @attachment.author_id = current_user.id
      @attachment.disk_directory = month_folder
      @attachment.cloud_url = remote_path
      @attachment.save!
    else
      logger.info "文件已存在，id = #{@attachment.id}, filename = #{@attachment.filename}"
    end

    render_json
  end

  def destroy
    begin
      @file_path = absolute_path(local_path(@file))
      #return normal_status(403, "") unless @file.author == current_user
      @file.destroy!

      delete_file(@file_path)
    rescue Exception => e
      uid_logger_error(e.message)
      tip_exception(e.message)
      raise ActiveRecord::Rollback
    end
  end

  private
  def find_file
    @file =
      if params[:type] == 'history'
        AttachmentHistory.find params[:id]
      else
        Attachment.find params[:id]
      end
  end

  def delete_file(file_path)
    File.delete(file_path) if File.exist?(file_path)
  end

  def current_month_folder
    date = Time.now
    "#{date.year}/#{date.month.to_s.rjust(2, '0')}"
  end

  def file_ext(file_name)
    ext = ''
    exts = file_name.split(".")
    if exts.size > 1
      ext = ".#{exts.last}"
    end
    ext
  end

  def file_save_to_local(save_path, temp_file, ext)
    unless Dir.exists?(save_path)
      FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
    end

    digest = md5_file(temp_file)
    digest = "#{digest}_#{Time.now.to_i}"
    local_file_path = File.join(save_path, digest) + ext
    save_temp_file(temp_file, local_file_path)

    [local_file_path, digest]
  end

  def save_temp_file(temp_file, save_file_path)
    File.open(save_file_path, 'wb') do |f|
      temp_file.rewind
      while (buffer = temp_file.read(8192))
        f.write(buffer)
      end
    end
  end

  def md5_file(temp_file)
    md5 = Digest::MD5.new
    temp_file.rewind
    while (buffer = temp_file.read(8192))
      md5.update(buffer)
    end
    md5.hexdigest
  end

  def file_save_to_ucloud(path, file, content_type)
    ufile = Educoder::Ufile.new(
        ucloud_public_key: edu_setting('public_key'),
        ucloud_private_key: edu_setting('private_key'),
        ucloud_public_read: true,
        ucloud_public_bucket: edu_setting('public_bucket'),
        ucloud_public_bucket_host: edu_setting('public_bucket_host'),
        ucloud_public_cdn_host: edu_setting('public_cdn_host'),
    )
    File.open(file) do |f|
      ufile.put(path, f, 'Content-Type' => content_type)
    end
    edu_setting('public_cdn_host') + "/" + path
  end

  def attachment_candown
    unless current_user.admin? || current_user.business?
      candown = true
      unless params[:type] == 'history'
        if @file.container && current_user.logged?
          # 课堂资源、作业、毕设相关资源的权限判断
          if @file.container.is_a?(Course)
            course = @file.container
            candown = current_user.member_of_course?(course) || (course.is_public? && @file.publiced?)
          elsif @file.container.is_a?(HomeworkCommon) || @file.container.is_a?(GraduationTask) || @file.container.is_a?(GraduationTopic)
            course = @file.container&.course
            candown = current_user.member_of_course?(course)
          elsif @file.container.is_a?(StudentWork)
            course = @file.container&.homework_common&.course
            candown = current_user.member_of_course?(course)
          elsif @file.container.is_a?(StudentWorksScore)
            course = @file.container&.student_work&.homework_common&.course
            candown = current_user.member_of_course?(course)
          elsif @file.container.is_a?(GraduationWork)
            course = @file.container&.graduation_task&.course
            candown = current_user.member_of_course?(course)
          elsif @file.container.is_a?(GraduationWorkScore)
            course = @file.container&.graduation_work&.graduation_task&.course
            candown = current_user.member_of_course?(course)
          end
          tip_exception(403, "您没有权限进入") if course.present? && !candown
        end
      end
    end
  end
end
