require 'oauth2'

class ApplicationController < ActionController::Base
	include CodeExample
	include RenderExpand
	include RenderHelper
	include ControllerRescueHandler
	include LaboratoryHelper
	include GitHelper
	include LoggerHelper
	include LoginHelper
	include RegisterHelper

	protect_from_forgery prepend: true, unless: -> { request.format.json? }

	before_action :check_sign
	before_action :user_setup
	#before_action :check_account

	# TODO
	# check sql query time
	before_action do
    # if request.subdomain === 'testforgeplus' || request.subdomain === "profiler"
    #   Rack::MiniProfiler.authorize_request
    # end
  end

	DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
	OPENKEY = "79e33abd4b6588941ab7622aed1e67e8"

	helper_method :current_user, :base_url

	# 所有请求必须合法签名
	def check_sign
		# if !Rails.env.development?
		# 	Rails.logger.info("66666  #{params}")
		# 	# suffix = request.url.split(".").last.split("?").first
		# 	# suffix_arr = ["xls", "xlsx", "pdf", "zip"] # excel文件先注释
		# 	# unless suffix_arr.include?(suffix)
		# 		if params[:client_key].present?
		# 			randomcode = params[:randomcode]
		# 			# tip_exception(501, "请求不合理") unless (Time.now.to_i - randomcode.to_i).between?(0,5)
		#
		# 			sign = Digest::MD5.hexdigest("#{OPENKEY}#{randomcode}")
		# 			Rails.logger.info("2222  #{sign}")
		# 			tip_exception(501, "请求不合理") if sign != params[:client_key]
		# 		else
		# 			tip_exception(501, "请求不合理")
		# 		end
		# 	# end
		# end
	end

	# 全局配置参数
	# 返回name对应的value
	def edu_setting(name)
		EduSetting.get(name)
	end

	# 平台身份权限判断（学生用户无权限）
	def identity_auth
		ue = current_user.user_extension
		tip_exception(403, "..") unless current_user.admin_or_business? || ue.teacher? || ue.professional?
	end

	# 平台已认证身份判断（已认证的老师和专业人士）
	def certi_identity_auth
		ue = current_user.user_extension
		tip_exception(403, "..") unless current_user.admin_or_business? ||
																									(current_user.professional_certification && (ue.teacher? || ue.professional?))
	end


	def admin_or_business?
		User.current.admin? || User.current.business? 
	end

	def admin_or_glcc_admin?
		User.current.admin? || User.current.glcc_admin?
	end

	# 判断用户的邮箱或者手机是否可用
	# params[:type] 1: 注册；2：忘记密码；3：绑定
	def  check_mail_and_phone_valid login, type
		unless login =~ /\A[a-zA-Z0-9]+([._\-\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/ || login =~ /^1\d{10}$/
			tip_exception(-2, "请输入正确的手机号或邮箱")
		end

		user_exist = Owner.exists?(phone: login) || Owner.exists?(mail: login)
		if user_exist && type.to_i == 1
			tip_exception(-2, "该手机号码或邮箱已被注册")
		elsif type.to_i == 2 && !user_exist
			tip_exception(-2, "该手机号码或邮箱未注册")
		elsif type.to_i == 3 && user_exist
			tip_exception(-2, "该手机号码或邮箱已绑定")
		end
		render_ok
	end

	# 发送及记录激活码
	# 发送验证码：type 1：注册手机验证码 2：找回密码手机验证码 3：找回密码邮箱验证码 4：绑定手机 5：绑定邮箱
	# 6：手机验证码登录 7：邮箱验证码登录 8：邮箱注册验证码 9：验证手机号有效
	def check_verification_code(code, send_type, value)
		case send_type
		when 1, 2, 4, 9
			# 手机类型的发送
			sigle_para = {phone: value}
			status = Gitlink::Sms.send(mobile: value, code: code)
			tip_exception(-2, code_msg(status)) if status != 0
		when 8, 3, 5
			# 邮箱类型的发送
			sigle_para = {email: value}
			# 60s内不能重复发送
			send_email_limit_cache_key = "send_email_60_second_limit:#{value}"
			tip_exception(-1, '请勿频繁操作') if Rails.cache.exist?(send_email_limit_cache_key)

			# 短时间内不能大量发送
			send_email_control = LimitForbidControl::SendEmailCode.new(value)
			tip_exception(-1, '邮件发送太频繁，请稍后再试') if send_email_control.forbid?
			begin
				UserMailer.register_email(value, code).deliver_now

				Rails.cache.write(send_email_limit_cache_key, 1, expires_in: 1.minute)
				send_email_control.increment!
				# Mailer.run.email_register(code, value)
			rescue Exception => e
				logger_error(e)
				tip_exception(-2,"邮件发送失败，请稍后重试")
			end
		end
		ver_params = { code_type: send_type, code: code, status: 1 }.merge(sigle_para)
		VerificationCode.create!(ver_params)
	end

	def code_msg status
		case status
		when 0
			"验证码已经发送到您的手机，请注意查收"
		when 8
			"同一手机号30秒内重复提交相同的内容"
		when 9
			"同一手机号5分钟内重复提交相同的内容超过3次"
		when 22
			"1小时内同一手机号发送次数超过限制"
		when 33
			"验证码发送次数超过频率"
		when 43
			"一天内同一手机号发送次数超过限制"
		when 53
			"手机号接收超过频率限制"
		end
	end

	def validate_type(object_type)
		normal_status(2, "参数") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
	end

	def set_pagination
		@page  		 = params[:page] || 1
		@page_size = params[:page_size] || 15
	end

	def require_admin
		normal_status(403, "") unless User.current.admin?
	end

	def require_business
		normal_status(403, "") unless admin_or_business?
	end

	def require_glcc_admin 
		normal_status(403, "") unless admin_or_glcc_admin?
	end

	# 前端会捕捉401,弹登录弹框
	# 未授权的捕捉407，弹试用申请弹框
	def require_login
		#6.13 -hs
		tip_exception(401, "请登录后再操作") unless User.current.logged?
	end

	def require_referer
		tip_exception(403, "你没有权限访问") if request.host.present? && !request.referer.to_s.include?(request.host.to_s.gsub("www.",""))
	end

	def require_login_or_token
		if params[:token].present?
			user = User.try_to_autologin(params[:token])
			User.current = user
		end
		tip_exception(401, "请登录后再操作") unless User.current.logged?
	end

	def require_login_cloud_ide_saas
		if params[:sign].present? && params[:email].present?
			sign = Digest::MD5.hexdigest("#{OPENKEY}#{params[:email]}")
			if params[:sign].to_s == sign
				user = User.find_by(mail: params[:email])
				User.current = user
			end
		end
		tip_exception(401, "请登录后再操作") unless User.current.logged?
	end

	def require_profile_completed
		# tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed?
	end

	def require_user_profile_completed(user)
		# tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed?
	end

	# 异常提醒
	def tip_exception(status = -1, message)
		raise Gitlink::TipException.new(status, message)
	end

	def missing_template
		tip_exception(404, "...")
	end

	# 弹框提醒
	def tip_show_exception(status = -2, message)
		raise Gitlink::TipException.new(status, message)
	end

	def normal_status(status = 0, message)
		case status
		when 403
			message = "您没有权限进行该操作"
		when 404
			message = "您访问的页面不存在或已被删除"
		end
		render :json => { status: status, message: message }
	end

	# 资料是否完善
	def check_account
		if !current_user. profile_is_completed?
			#info_url = '/account/profile'
			tip_exception(402, nil)
		end
	end

	# 系统全局认证(暂时隐藏试用申请的判断)
	def check_auth
		# day_cer = UserDayCertification.find_by(user_id: current_user.id)
		# # 如果注册超过24小时则需要完善资料及授权
		# if (Time.now.to_i - day_cer.try(:created_at).to_i) > 86400
		# 	if !current_user.profile_completed?
		# 		info_url = '/account/profile'
		# 		tip_exception(402, info_url)
		# 	elsif current_user.certification != 1
		# 		if current_user.apply_actions.exists?(container_type: 'TrialAuthorization', status: 0)
		# 			tip_exception(408, "您的试用申请正在审核中，请耐心等待")
		# 		end
		# 		tip_exception(407, "系统未授权")
		# 	end
		# end


		# if current_user.certification != 1 && current_user.apply_actions.exists?(container_type: 'TrialAuthorization', status: 0)
		# 	tip_exception(408, "您的试用申请正在审核中，请耐心等待")
		# elsif (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400
		# 	if !current_user.profile_completed?
		# 		info_url = '/account/profile'
		# 		tip_exception(402, info_url)
		# 	elsif current_user.certification != 1
		# 		day_cer = UserDayCertification.find_by(user_id: current_user.id)
		# 		tip_exception(407, "系统未授权") unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400
		# 	end
		# end
	end

	def user_setup
		# # reacct静态资源加载不需要走这一步
		#return if params[:controller] == "main"
		# Find the current user
		#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
		if request.headers["Authorization"].present? && request.headers["Authorization"].start_with?('Bearer')
			if !valid_doorkeeper_token?
				header = request.authorization
				pattern = /^Bearer /i
				token = header.gsub(pattern, "")
				User.current, message = Bot.decode_jwt_token(token)
				tip_exception(401, message) if message.present?
			else
				if @doorkeeper_token.present?
					# client方法对接，需要一直带着用户标识uid
					if @doorkeeper_token.resource_owner_id.blank?
						tip_exception(-1, "缺少用户标识!") if params[:uid].nil?
						User.current = User.find(params[:uid])
					else
						User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
					end
				end
			end
		else
			User.current = find_current_user
			uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))

			if !User.current.logged? && Rails.env.development?
				user = User.find 1
				User.current = user
				start_user_session(user)
			end


			# 测试版前端需求
			logger.info("subdomain:#{request.subdomain}")
			if request.subdomain != "www"
				if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
					User.current = User.find 6
				elsif params[:debug] == 'student'
					User.current = User.find 7
				elsif params[:debug] == 'admin'
					logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
					user =  User.find 1
					User.current = user
					cookies.signed[:user_id] = user.id
				end
			end
		end
		UserOnline.login(User.current.id)
		# User.current = User.find 81403
	end

	# Returns the current user or nil if no user is logged in
	# and starts a session if needed
	def find_current_user
		uid_logger("user setup start: session[:user_id] is #{session[:user_id]}")
		uid_logger("0000000000000user setup start: default_yun_session is #{default_yun_session}, session[:current_user_id] is #{session[:"#{default_yun_session}"]}")
		current_domain_session = session[:"#{default_yun_session}"]
		autologin_user = try_to_autologin
		uid_logger("user setup start: autologin_user is #{autologin_user}")
		# 多浏览器退出账号时，token不存在处理
		if current_domain_session && autologin_user.nil?
			autologin_user = (User.active.find(current_domain_session) rescue nil)
			set_autologin_cookie(autologin_user) if autologin_user.present?
		end
		autologin_user
	end

	def try_to_autologin
		if cookies[autologin_cookie_name]
			# auto-login feature starts a new session
			user = nil
			Rails.logger.info("111111111111111111#{default_yun_session}, session is #{session[:"#{default_yun_session}"]} ")
			user = User.try_to_autologin(cookies[autologin_cookie_name])
			# start_user_session(user) if user # TODO 解决sso退出不同步的问题
			user
		elsif params[:token].present?
			User.try_to_autologin(params[:token])
		end
	end

	def api_request?
		%w(xml json).include? params[:format]
	end

	def current_user
		User.current
	end

	## 默认输出json
	def render_json
		respond_to do |format|
      format.json
    end
	end

	## 输出错误信息
	def error_status(message = nil)
		@status = -1
		@message = message
	end

	# 实训等对应的仓库地址
	def repo_ip_url(repo_path)
		"#{edu_setting('git_address_ip')}/#{repo_path}"
	end

	def repo_url(repo_path)
		"#{edu_setting('git_address_domain')}/#{repo_path}"
	end

	# Post请求
	def uri_post(uri, params)
		begin
			uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}")
			uri = URI.parse(URI.encode(uri.strip))
			res = Net::HTTP.post_form(uri, params).body
			uid_logger_dubug("--uri_exec: .....res is #{res}")
			JSON.parse(res)
		rescue Exception => e
			uid_logger_error("--uri_exec: exception #{e.message}")
			raise Gitlink::TipException.new("实训平台繁忙（繁忙等级：84）")
		end
	end

	#　处理返回非０就报错的请求
	def interface_post(uri, params, status, message)
		begin
			uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}")
			uri = URI.parse(URI.encode(uri.strip))
			res = Net::HTTP.post_form(uri, params).body
			uid_logger_dubug("--uri_exec: .....res is #{res}")
			res = JSON.parse(res)
			if (res && res['code'] != 0)
				tip_exception(status, message)
			else
				res
			end
		rescue Exception => e
			uid_logger("--uri_exec: exception #{e.message}")
			raise Gitlink::TipException.new(message)
		end
	end

	# json格式请求
	def interface_json_post(uri, params, status, message)
		begin
			uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}")
			uri = URI.parse(URI.encode(uri.strip))
			res = Net::HTTP.start(uri.host, uri.port) do |http|
				req = Net::HTTP::Post.new(uri)
				req['Content-Type'] = 'application/json'
				req.body = params.to_json
				http.request(req)
			end
			uid_logger_dubug("--uri_exec: .....res is #{res.body}")
			res = JSON.parse(res.body)
			if (res && res['code'] != 0)
				tip_exception(status, message)
			else
				res
			end
		rescue Exception => e
			uid_logger("--uri_exec: exception #{e.message}")
			raise Gitlink::TipException.new("服务器繁忙")
		end
	end


	# 适用与已经用url_safe编码后，回调字符串形式
	def tran_base64_decode64(str)
		s_size = str.size % 4
		if s_size != 0
			str += "=" * (4 - s_size)
		end
		if str.blank?
			str
		else
			Base64.decode64(str.tr("-_", "+/")).force_encoding("utf-8")
		end
	end

	def sucess_status(message = 'success')
		render :json => { status: 1, message: message }
	end

	# 随机生成字符
	def generate_identifier(container, num, pre='')
		code = DCODES.sample(num).join
		if container == User
			while container.exists?(login: pre+code) do
				code = DCODES.sample(num).join
			end
		else
			while container.exists?(identifier: code) do
				code = DCODES.sample(num).join
			end
		end
		code
	end


	def strip_html(text, len=0, endss="...")
		ss = ""
		if !text.nil? && text.length>0
			ss=text.gsub(/<\/?.*?>/, '').strip
			ss = ss.gsub(/&nbsp;*/, '')
			ss = ss.gsub(/\r\n/,'')  #新增
			ss = ss.gsub(/\n/,'')  #新增
			if len > 0 && ss.length > len
				ss = ss[0, len] + endss
			elsif len > 0 && ss.length <= len
				ss = ss
				#ss = truncate(ss, :length => len)
			end
		end
		ss
	end

	# Returns a string that can be used as filename value in Content-Disposition header
	def filename_for_content_disposition(name)
		request.env['HTTP_USER_AGENT'] =~ %r{MSIE|Trident|Edge} ? ERB::Util.url_encode(name) : name
	end

	def format_time(time)
		time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M")
	end

	# 获取Oauth Client
	def get_client(site)
		client_id = Rails.configuration.Gitlink['client_id']
		client_secret = Rails.configuration.Gitlink['client_secret']

		OAuth2::Client.new(client_id, client_secret, site: site)
	end

	def paginate(relation)
		limit = params[:limit] || params[:per_page]
		limit  = (limit.to_i.zero? || limit.to_i > 200) ? 20 : limit.to_i
		page   = params[:page].to_i.zero? ? 1 : params[:page].to_i
		offset = (page - 1) * limit

		if relation.is_a?(Array)
			relation[offset, limit]
		else
			relation.limit(limit).offset(offset)
		end
	end

	def kaminari_paginate(relation)
		limit = params[:limit] || params[:per_page]
		limit = (limit.to_i.zero? || limit.to_i > 50) ? 50 : limit.to_i
		page  = params[:page].to_i.zero? ? 1 : params[:page].to_i

		relation.page(page).per(limit)
	end

	def kaminari_unlimit_paginate(relation)
		limit = params[:limit] || params[:per_page]
		limit = (limit.to_i.zero? || limit.to_i > 9999) ? 9999 : limit.to_i
		page  = params[:page].to_i.zero? ? 1 : params[:page].to_i

		relation.page(page).per(limit)
	end

	def kaminari_array_paginate(relation)
		limit = params[:limit] || params[:per_page]
		limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
		page  = params[:page].to_i.zero? ? 1 : params[:page].to_i

		Kaminari.paginate_array(relation).page(page).per(limit)
	end

	def strf_time(time)
		time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M:%S")
	end

	def strf_date(date)
		date.blank? ? '' : date.to_date.strftime("%Y-%m-%d")
	end

	def logger_error(error)
		Rails.logger.error(error.message)
		error.backtrace.each { |msg| Rails.logger.error(msg) }
	end

	def find_user
		@user = User.find_by_login params[:login]
    render_not_found("未找到’#{params[:login]}’相关的用户") unless @user
	end

	def find_user_with_id
		@user = User.find_by(type: 'User', id: params[:user_id])
    # render_not_found("未找到’#{params[:login]}’相关的用户") unless @user
		render_error("未找到相关的用户") unless @user
	end

	def find_repository
		@repo = @user.repositories.find_by_identifier params[:repo_identifier]
    render_not_found("未找到’#{params[:repo_identifier]}’相关的项目") unless @repo
	end

	def find_repository_by_id
		@repo = Repository.find params[:id]
	end

	def find_project
		project_id = params[:project_id] ? params[:project_id] : params[:id]
		project = Project.where(identifier: project_id)
		if project.exists?
			@project = project.first
		else
			@project = Project.find project_id
		end

		render_not_found("未找到’#{project}’相关的项目") unless @project
	end

	def find_project_with_id
		@project = Project.find(params[:project_id] || params[:id])
	rescue Exception => e
		logger_error(e.message)
		tip_exception(e.message)
	end

	def render_response(interactor)
		interactor.success? ? render_ok : render_error(interactor.error)
	end

	# projects
	def load_project
    namespace = params[:owner]
    id = params[:repo] || params[:id]

    @project, @owner = Project.find_with_namespace(namespace, id)

    if @project and (current_user.can_read_project?(@project) || controller_path == "projects/project_invite_links")
			logger.info "###########： has project and can read project"
			@project
    # elsif @project && current_user.is_a?(AnonymousUser)
		# 	logger.info "###########：This is AnonymousUser"
		# 	@project = nil if !@project.is_public?
		# 	render_forbidden and return
    else
			if @project.present? 
				logger.info "###########： has project and but can't read project"
				@project = nil
				render_forbidden and return
			else 
				logger.info "###########：project not found"
				@project = nil
				render_not_found and return
			end
    end
    @project
	end

	def load_repository
		@repository ||= load_project&.repository
	end

	def base_url
		Rails.application.config_for(:configuration)['platform_url'] || request.base_url
	end

	def image_type?(str)
    default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
    default_type.include?(str&.downcase)
  end

	def convert_image!
		@image = params[:image]
		@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
    return unless @image.present?
    max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
    if @image.class == ActionDispatch::Http::UploadedFile
      return render_error('请上传文件') if @image.size.zero?
      return render_error('文件大小超过限制') if @image.size > max_size.to_i
			return render_error('头像格式不正确！') unless image_type?(File.extname(@image.original_filename.to_s)[1..-1])
    else
      image = @image.to_s.strip
      return render_error('请上传正确的图片') if image.blank?
      @image = Util.convert_base64_image(image, max_size: max_size.to_i)
    end
  rescue Base64ImageConverter::Error => ex
    render_error(ex.message)
	end

  def avatar_path(object)
    ApplicationController.helpers.disk_filename(object.class, object.id)
  end

  private
	def object_not_found
		uid_logger("Missing template or cant't find record, responding with 404")
		render json: {message: "您访问的页面不存在或已被删除", status: 404}
		false
	end

	def tip_show(exception)
		uid_logger("Tip show status is #{exception.status}, message is #{exception.message}")
		render json: exception.tip_json
	end

	def render_parameter_missing
		render json: { status: -1, message: '参数缺失' }
	end

	def set_export_cookies
		cookies[:fileDownload] = true
	end

	# 记录热门搜索关键字
	def record_search_keyword
		keyword = params[:keyword].to_s.strip
		return if keyword.blank? || keyword.size <= 1
		return unless HotSearchKeyword.available?

		HotSearchKeyword.add(keyword)
	end

	# author: zxh
	# blockchain相关项目活动调用函数
	# return true: 表示上链操作成功; return false: 表示上链操作失败
		def push_activity_2_blockchain(activity_type, model)
		if activity_type == "issue_create"

			project_id = model['project_id']
			project = Project.find(project_id)
			if project['use_blockchain'] == 0 || project['use_blockchain'] == false
				# 无需执行上链操作
				return true
			end

			id = model['id']

			owner_id = project['user_id']
			owner = User.find(owner_id)
			ownername = owner['login']
			identifier = project['identifier']

			author_id = project['user_id']
			author = User.find(author_id)
			username = author['login']

			action = 'opened'

			title = model['subject']
			content = model['description']
			created_at = model['created_on']
			updated_at = model['updated_on']

			# 调用区块链接口
			params = {
				"request-type": "upload issue info",
				"issue_id": "gitlink-" + id.to_s,
				"repo_id": "gitlink-" + project_id.to_s,
				"issue_number": 0, # 暂时不需要改字段
				"reponame": identifier,
				"ownername": ownername,
				"username": username,
				"action": action,
				"title": title,
				"content": content,
				"created_at": created_at,
				"updated_at": updated_at
			}.to_json
			resp_body = Blockchain::InvokeBlockchainApi.call(params)
			if resp_body['status'] == 10
				raise ApplicationService::Error, resp_body['message']
			elsif resp_body['status'] != 0
				raise ApplicationService::Error, "区块链接口请求失败."
			end

		elsif activity_type == "issue_comment_create"
			issue_comment_id = model['id']
			issue_id = model['journalized_id']
			parent_id = model['parent_id'].nil? ? "" : model['parent_id']

			issue = Issue.find(issue_id)
			issue_classify = issue['issue_classify'] # issue或pull_request
			project_id = issue['project_id']
			project = Project.find(project_id)

			if project['use_blockchain'] == 0 || project['use_blockchain'] == false
				# 无需执行上链操作
				return
			end

			identifier = project['identifier']
			owner_id = project['user_id']
			owner = User.find(owner_id)
			ownername = owner['login']

			author_id = model['user_id']
			author = User.find(author_id)
			username = author['login']

			action = 'created'

			content = model['notes']
			created_at = model['created_on']

			if issue_classify == "issue"
				params = {
					"request-type": "upload issue comment info",
					"issue_comment_id": "gitlink-" + issue_comment_id.to_s,
					"issue_comment_number": 0, # 暂时不需要
					"issue_number": 0, # 暂时不需要
					"issue_id": "gitlink-" + issue_id.to_s,
					"repo_id": "gitlink-" + project.id.to_s,
					"parent_id": parent_id.to_s,
					"reponame": identifier,
					"ownername": ownername,
					"username": username,
					"action": action,
					"content": content,
					"created_at": created_at,
				}.to_json
			elsif issue_classify == "pull_request"
				params = {
					"request-type": "upload pull request comment info",
					"pull_request_comment_id": "gitlink-" + issue_comment_id.to_s,
					"pull_request_comment_number": 0, # 不考虑该字段
					"pull_request_number": 0, # 不考虑该字段
					"pull_request_id": "gitlink-" + issue_id.to_s,
					"parent_id": parent_id.to_s,
					"repo_id": "gitlink-" + project.id.to_s,
					"reponame": identifier,
					"ownername": ownername,
					"username": username,
					"action": action,
					"content": content,
					"created_at": created_at,
				}.to_json
			end

			# 调用区块链接口
			resp_body = Blockchain::InvokeBlockchainApi.call(params)
			if resp_body['status'] == 10
				raise ApplicationService::Error, resp_body['message']
			elsif resp_body['status'] != 0
				raise ApplicationService::Error, "区块链接口请求失败."
			end
		elsif activity_type == "pull_request_create"
			# 调用区块链接口
			project_id = model['project_id']
			project = Project.find(project_id)
			if project['use_blockchain'] == 0 || project['use_blockchain'] == false
				# 无需执行上链操作
				return
			end

			pull_request_id = model['id']
			identifier = project['identifier']
			owner_id = project['user_id']
			owner = User.find(owner_id)
			ownername = owner['login']

			action = 'opened'

			title = model['title']
			content = model['body']

			source_branch = model['head']
			source_repo_id = model['fork_project_id'].nil? ? project_id : model['fork_project_id']

			target_branch = model['base']
			target_repo_id = project_id

			author_id = model['user_id']
			author = User.find(author_id)
			username = author['login']

			created_at = model['created_at']
			updated_at = model['updated_at']

			# 查询pull request对应的commit信息
			commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'], current_user&.gitea_token)
			if commits.nil?
				raise ApplicationService::Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
			end
			commit_shas = []
			commits.each do |c|
				commit_shas << c["Sha"]
			end
			params = {
				"request-type": "upload pull request info",
				"pull_request_id": "gitlink-" + pull_request_id.to_s,
				"pull_request_number": 0, # trustie没有该字段
				"repo_id": "gitlink-" + project_id.to_s,
				"ownername": ownername,
				"reponame": identifier,
				"username": username,
				"action": action,
				"title": title,
				"content": content,
				"source_branch": source_branch,
				"target_branch": target_branch,
				"reviewers": [], # trustie没有该字段
				"commit_shas": commit_shas,
				"merge_user": "", # trustie没有该字段
				"created_at": created_at,
				"updated_at": updated_at
			}.to_json
			resp_body = Blockchain::InvokeBlockchainApi.call(params)
			if resp_body['status'] == 9
				raise ApplicationService::Error, resp_body['message']
			elsif resp_body['status'] != 0
				raise ApplicationService::Error, "区块链接口请求失败."
			end
		elsif activity_type == "pull_request_merge"
			# 调用区块链接口
			project_id = model['project_id']
			project = Project.find(project_id)
			if project['use_blockchain'] == 0 || project['use_blockchain'] == false
				# 无需执行上链操作
				return
			end

			pull_request_id = model['id']
			identifier = project['identifier']
			owner_id = project['user_id']
			owner = User.find(owner_id)
			ownername = owner['login']

			action = 'merged'

			created_at = model['created_at']
			updated_at = model['updated_at']

			# 查询pull request对应的commit信息
			commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'], current_user&.gitea_token)
			if commits.nil?
				raise ApplicationService::Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
			end
			commit_shas = []
			commits.each do |c|
				commit_shas << c["Sha"]
			end

			# 将pull request相关信息写入链上
			params = {
				"request-type": "upload pull request info",
				"pull_request_id": "gitlink-" + pull_request_id.to_s,
				"pull_request_number": 0, # trustie没有该字段
				"repo_id": "gitlink-" + project_id.to_s,
				"ownername": ownername,
				"reponame": identifier,
				"username": username,
				"action": action,
				"title": title,
				"content": content,
				"source_branch": source_branch,
				"target_branch": target_branch,
				"reviewers": [], # trustie没有该字段
				"commit_shas": commit_shas,
				"merge_user": "", # trustie没有该字段
				"created_at": created_at,
				"updated_at": updated_at
			}.to_json
			resp_body = Blockchain::InvokeBlockchainApi.call(params)
			if resp_body['status'] == 9
				raise ApplicationService::Error, resp_body['message']
			elsif resp_body['status'] != 0
				raise ApplicationService::Error, "区块链接口请求失败."
			end


			# 将commit相关信息写入链上
			commit_shas.each do |commit_sha|
				commit_diff = Gitea::Commit::DiffService.call(ownername, identifier, commit_sha, owner['gitea_token'])
				commit = Gitea::Commit::InfoService.call(ownername, identifier, commit_sha, owner['gitea_token'])
				params = {
					"request-type": "upload commit info",
					"commit_hash": commit_sha,
					"repo_id": "gitlink-" + project_id.to_s,
					"author": commit['commit']['author']['name'],
					"author_email": commit['commit']['author']['email'],
					"committer": commit['commit']['committer']['name'],
					"committer_email": commit['commit']['committer']['email'],
					"author_time": commit['commit']['author']['date'],
					"committer_time": commit['commit']['committer']['date'],
					"content": commit['commit']['message'],
					"commit_diff": commit_diff.present? ? commit_diff['Files'].to_s : ""
				}.to_json
				resp_body = Blockchain::InvokeBlockchainApi.call(params)
				if resp_body['status'] == 7
					raise ApplicationService::Error, resp_body['message']
				elsif resp_body['status'] != 0
					raise ApplicationService::Error, "区块链接口请求失败."
				end
			end

		elsif activity_type == "pull_request_refuse"

			# 调用区块链接口
			project_id = model['project_id']
			project = Project.find(project_id)
			if project['use_blockchain'] == 0 || project['use_blockchain'] == false
				# 无需执行上链操作
				return true
			end

			pull_request_id = model['id']
			identifier = project['identifier']
			owner_id = project['user_id']
			owner = User.find(owner_id)
			ownername = owner['login']

			action = 'refused'

			# 将pull request相关信息写入链上
			params = {
				"request-type": "upload pull request info",
				"pull_request_id": "gitlink-" + pull_request_id.to_s,
				"pull_request_number": 0, # trustie没有该字段
				"repo_id": "gitlink-" + project_id.to_s,
				"ownername": ownername,
				"reponame": identifier,
				"username": username,
				"action": action,
				"title": title,
				"content": content,
				"source_branch": source_branch,
				"target_branch": target_branch,
				"reviewers": [], # trustie没有该字段
				"commit_shas": commit_shas,
				"merge_user": "", # trustie没有该字段
				"created_at": created_at,
				"updated_at": updated_at
			}.to_json
			resp_body = Blockchain::InvokeBlockchainApi.call(params)
			if resp_body['status'] == 9
				raise ApplicationService::Error, resp_body['message']
			elsif resp_body['status'] != 0
				raise ApplicationService::Error, "区块链接口请求失败."
			end
		end
	end
  def find_atme_receivers
    @atme_receivers = User.where(login: params[:receivers_login])
	end

	# 接口限流，请求量大有性能问题
	def request_limit
		white_list_ip  = ["106.75.110.152"]
		unless white_list_ip.include?(request.remote_ip)
			record_count = Rails.cache.read("request/#{controller_name}/#{Time.now.strftime('%Y%m%d%H')}/#{request.remote_ip}")
			if record_count.present?
				record_count = record_count + 1
			else
				record_count = 1
			end
			Rails.logger.info("请求太快，请稍后再试。#{controller_name}::#{request.remote_ip}") if record_count > 200
			tip_exception("请求太快，请稍后再试。") if record_count > 200

			Rails.cache.write("request/#{controller_name}/#{Time.now.strftime('%Y%m%d%H')}/#{request.remote_ip}", record_count, expires_in: 1.hour)
		end
	end

	def check_batch_requests
		check_key = "request.remote_ip:#{request.remote_ip}"
		result = Rails.cache.read(check_key)
		if result.present?
			if result.to_i > 100
				tip_exception(401, '暂时无法请求，请稍后再试')
			else
				Rails.cache.write(check_key, result.to_i + 1)
			end
		else
			Rails.cache.write(check_key, 1, expires_in: 1.hour)
		end
	end

	def request_raw_limit
		record_count = Rails.cache.read("request/#{request.path}/#{Time.now.strftime('%Y%m%d%H')}}")
		if record_count.present?
			record_count = record_count + 1
		else
			record_count = 1
		end
		Rails.logger.info("请求太快，请稍后再试。#{request.path}") if record_count > 1000
		tip_exception("请求太快，请稍后再试。") if record_count > 1000

		Rails.cache.write("request/#{request.path}/#{Time.now.strftime('%Y%m%d%H')}}", record_count, expires_in: 1.hour)
	end

end
