class Projects::LinkJoinService < ApplicationService
  Error = Class.new(StandardError)

  attr_reader :user, :project, :invite_sign, :params

  def initialize(user, project, invite_sign, params={})
    @user        = user
    @project     = project
    @invite_sign = invite_sign
    @params      = params
  end

  def call
    ActiveRecord::Base.transaction do
      validate! 
      if invite_link.is_apply 
        # 如果需要申请才能加入，创建一条申请记录
        create_applied_project!
      else
        # 如果不需要申请，直接为项目添加该成员
        create_member!
      end
    end
  end

  private
  def validate! 
    raise Error, 'invite_sign必须存在!' if invite_sign.blank?
    raise Error, '邀请链接不存在!' unless invite_link.present?
    raise Error, '邀请链接已失效!' unless invite_user_in_project
    raise Error, '您已是仓库成员' if project.member?(user.id)
    raise Error, '您的申请管理员正在审核中，请勿重复申请！' if user.applied_projects.exists?(applied_project_params)
  end

  def applied_project_params 
    {
      status: 'common',
      project: project,
      role: role_value,
      project_invite_link_id: invite_link&.id
    }
  end

  def create_applied_project!
    user.applied_projects.find_or_create_by!(status: 'common', project: project, role: role_value, project_invite_link_id: invite_link&.id)
  end

  def create_member!
    Projects::AddMemberInteractor.call(project.owner, project, user, permission)
  end

  def invite_link 
    ProjectInviteLink.find_by(project_id: project.id, sign: invite_sign)
  end

  def invite_user_in_project 
    in_project = project.member?(invite_link.user)
    invite_link.update_column(:expired_at, Time.now) unless in_project
    in_project
  end

  def role_value
    @_role ||=
      case invite_link&.role
      when 'manager'   then 3
      when 'developer' then 4
      when 'reporter'  then 5
      else 
        5
      end
  end

  def permission 
    case invite_link&.role 
    when 'manager'
      'admin'
    when 'developer'
      'write'
    when 'reporter'
      'read'
    else 
      'read'
    end
  end

end