#encoding=utf-8
# 云启训练场（EduCoder）个人版	产品编码（appId）	9200108
# 产品名称	计费类型	套餐编码
# 云启训练场（EduCoder）个人版	固定包月	9200108001
#                           固定包月	9200108002
#                           固定包月	9200108003
# ---------------------------------------------------
# 产品名称	计费类型	套餐编码
# 云启训练场（EduCoder））院校版	包月+按license	9200109001
# 包月+按license	9200109002

# 云启训练场（EduCoder））院校版	产品编码（appId）	9200109

require 'net/http'
require 'digest'

class EcloudController < ApplicationController

  before_action :save_para
  before_action :check_sign_key, only: [:ps_new, :ps_update, :bs_new, :bs_update]


  def index
    render file: 'public/react-oschina/build/index.html', :layout => false
  end

  def trustie_login
  end

  # 测试环境
  # CLIENT_ID = '1022'
  # CLIENT_SECRET = '2112037a-6d7a-432b-9081-feb1153d8668'
  # SERVER_URL = "https://221.176.54.92:9081/restful/services/"
  #

  # 正式环境
  CLIENT_ID = '1056'
  CLIENT_SECRET = '2e84256a-3de4-4713-9e02-10ee88a14592'
  SERVER_URL = "https://221.176.53.130:44390/services/"


  ## 签名
  def sign(timestamp)
    Digest::MD5.hexdigest("client_id=#{CLIENT_ID}client_key=#{CLIENT_SECRET}timestamp=#{timestamp}").upcase
  end


  # 企业/个人业务开通
  # applyno 申请单号，唯一
  # ecordercode 唯一标志一个企业的订购关系
  # params['opttype']：操作类型。0开通；1变更；2试用转商用；4再次开通
  # 业务列表opttype: 0新增；1注销；2修改
  # serviceparas: 但是由于企业版是按成员收费的，所以serviceparas里面会传成员数；个人版是包月计费的，serviceparas不会传成员数
  def bs_new
    ActiveRecord::Base.transaction do
      begin
        if params['opttype'] == 0 # 开通企业/个人业务
          ecloud = Ecloud.create!(eloud_params)
          create_service(params['services'], ecloud.try(:id)) if params['services'].present?
          create_product_params(params['productparas'],  ecloud.try(:id)) if params['productparas'].present?
          # 为管理员添加一条记录
          # 开通的时候都是用户的opttype也是0
          # 如果管理员已经存在，则不用重复开通
          euser = EcloudUser.where(userid: params['userid'], custid: params['custid']).first
          unless euser
            EcloudUser.create!(custid: params['custid'], opttype: params['opttype'], userid: params['userid'],
                               username: params['username'], useralias: params['useralias'],
                               mobile: params['mobile'], email: params['email'],  begintime: params['begintime'],
                               endtime: params['endtime'])
          end
        elsif params['opttype'] == 2 # 试用转商用 # 变更企业/个人业务
          # 业务列表：注销业务(注销试用的套餐)，另一个业务项的操作代码是：新增业务(开通商用的套餐)
          # 需要通过产品服务编号和业务编码来区分哪个产品
          ecloud = Ecloud.where(custid: params['custid'], custcode: params['custcode'], productcode: params['productcode'], trial: true).first

          # 注销试用的套餐
          ## 需要注销的套餐; 试用转商用是不会有批量操作的，所以可以使用first
          des_service = params['services'].select{|s| s['opttype'] == 1}.first
          esd = EcloudService.where(ecloud_id: ecloud.try(:id), code: des_service['code']).first
          ecloud.update_attribute(:trial, params['trial'])
          esd.update_attributes!(opttype: des_service['opttype'], begintime: des_service['begintime'], endtime: des_service['endtime'])

          # 试用转商用是不会有批量操作的
          # 新增业务
          add_service =  params['services'].select{|s| s['opttype'] == 0}
          create_service(add_service, ecloud.try(:id))
          #

        elsif params['opttype'] == 1 # 业务变更
          ecloud = Ecloud.where(custid: params['custid'], custcode: params['custcode'], productcode: params['productcode']).first
          # 套餐变更
          # 操作代码 0：新增业务，1：注销业务2：修改业务
          # # 新增服务
          add_service = params['services'].select{|s| s['opttype'] == 0}
          create_service(add_service, ecloud.try(:id)) if add_service.present?

          # 如果有注销业务，注销业务
          des_services = params['services'].select{|s| s['opttype'] == 1}
          if des_services.present?
            des_services.each do |ds|

              logger.info("666666#{ecloud.try(:id)}, 55555555#{ds['code']}")
              esd = EcloudService.where(ecloud_id: ecloud.try(:id), code: ds['code']).first
              esd.update_attributes!(opttype: ds['opttype'], begintime: ds['begintime'], endtime: ds['endtime'])
            end
          end

          # 变更业务
          edt_services = params['services'].select{|s| s['opttype'] == 2}
          if edt_services.present?
            edt_services.each do |es|
              ese = EcloudService.where(ecloud_id: ecloud.try(:id), code: es['code']).first
              ese.update_attributes!(opttype: es['opttype'], begintime: es['begintime'], endtime: es['endtime']) if ese.present?
              create_serviceparas(es['serviceparas'].first, ese.id) if ese.present?
            end
          end


          # ecloud = Ecloud.where(bossorderid: params['bossorderid']).first
          # ecloud.update_attributes!(eloud_params)
          # ecloud.ecloud_productparas.destroy
          # ecloud.ecloud_services.destroy
          #
          # ecloud_id = ecloud.try(:id)

        elsif params['opttype'] == 4 # 再次重复开通
          # 再次申请开通，这种情况就是累加时间
          ecloud = Ecloud.where(custid: params['custid'], custcode: params['custcode'], productcode: params['productcode']).first
          create_service(params['services'], ecloud.try(:id))
          create_product_params(params['productparas'],  ecloud.try(:id)) if params['productparas'].present?
        end

        #
        # # 非试用情况下，为管理员单独创建一条账号，企业账号
        # unless  params['trial']
        #   EcloudUser.create!(ecloud_id: ecloud.try(:id), opttype: params['opttype'], userid: params['userid'],
        #                      username: params['username'], useralias: params['useralias'],
        #                      mobile: params['mobile'],  email: params['email'])
        # end

        render :json => {result: true, errmsg: ""}
        # rescue Exception => e
        #   logger.error(e.message)
        #   render :json => {code: 500, msg: "#{e.message}"}
        #   raise ActiveRecord::Rollback
      end
    end
  end

  # 企业/个人业务变更、注销
  # 处理业务平台退订、暂停（欠费暂停，信控暂停等）、暂停后恢复应用业务
  # 这个接口是不会新增业务的
  # 试用退订的时候bossorderid传空字符
  def bs_update
    ActiveRecord::Base.transaction do
      begin
        case params['opttype']
        when 0 # 退订
          opttype = 6
        when 1 # 暂停
          opttype = 7
        when 2 # 恢复
          opttype = 8
        end
        if params['bossorderid'].present?
          ecloud = Ecloud.where(bossorderid: params['bossorderid']).first
          ecloud.update_attribute(:opttype, opttype)
        else
          # 试用退订
          params['services'].each do |service|
            ecloud_id = EcloudService.where(code: service['packagecode']).first.try(:ecloud_id)
            Ecloud.find(ecloud_id).update_attribute(:opttype, opttype)
          end
        end
        render :json => {result: true, errmsg: ""}
      rescue Exception => e
        logger.error(e.message)
        render :json => {code: 500, msg: "#{e.message}"}
        raise ActiveRecord::Rollback
      end
    end
  end

  # 用户业务开通与变更接口
  # 授权statu为1，取消授权status为0
  # user['opttype']: 操作类型0：开通；1：变更；3: 取消授权；4：暂停；5：恢复；

  def ps_new
    ActiveRecord::Base.transaction do
      begin
        user_params = params['users']
        user_params.each do |user_param|
          if user_param['opttype'] == 0 # 开通
            EcloudUser.create!(custid: params['custid'], opttype: user_param['opttype'], userid: user_param['userid'],
                               username: user_param['username'], useralias: user_param['useralias'],
                               mobile: user_param['mobile'],  email: user_param['email'],  begintime: user_param['begintime'].to_s,
                               endtime: user_param['endtime'].to_s)
          elsif user_param['opttype'] == 1 # 变更
            ecloud_user = EcloudUser.where(custid: params['custid'], userid: user_param['userid']).first
            ecloud_user.update_attributes!(opttype: user_param['opttype'],  username: user_param['username'],
                                           useralias: user_param['useralias'], mobile: user_param['mobile'],  email: user_param['email'],
                                           begintime: user_param['begintime'].to_s, endtime: user_param['endtime'].to_s)
          end
        end

        render :json => {success: true, errmsg: ""}
          # end
      rescue Exception => e
        logger.error(e.message)
        render :json => {code: 500, msg: "#{e.message}"}
        raise ActiveRecord::Rollback
      end
    end
  end

  # 用户业务状态变更
  # user['opttype']: 操作类型0：开通；1：变更；3: 取消授权；4：暂停；5：恢复；
  def ps_update
    begin
      user_params = params['users']
      user_params.each do |user_param|
        case user_param['opttype']
        when 0 # 取消授权
          opttype = 3
        when 1 # 暂停
          opttype = 4
        when 2 # 恢复
          opttype = 5
        end
        ecloud_user = EcloudUser.where(custid: params['custid'], userid: user_param['userid']).first
        ecloud_user.update_attributes!(opttype: opttype, operatime: params['operatime'], effecttime: params['effecttime'])
      end

      render :json => {success: true, errmsg: ""}
    rescue Exception => e
      logger.error(e.message)
      render :json => {code: 500, msg: "#{e.message}"}
    end
  end

  def ecloud_login_callback
    if params[:test]
      user_info = decode '{"userid":2147,"custid":2104,"custcode":"E0002018042810010054","custtype":2,"status":2,"username":"15111030087@QW_er","useralias":"15111030087","isadmin":true,"entprise":"04**004","departments":"","departmentnames":"","mobile":"15365386520","email":"15111030087@139.com"}'
    else
      res = request_ecloud_authorization

      logger.info "oauth2 authorization resp: #{res}"
      raise '登录失败' unless res["access_token"]

      user_info = decode get_ecloud_user(res)
      logger.info "oauth2 get user info: #{user_info}"
    end

    open_user = OpenUsers::Ecloud.find_or_initialize_by(uid: user_info['userid']) do |u|
      u.extra = user_info
    end

    redirect_to "/users/#{open_user.user.login}/courses" and return  if open_user.persisted?

    ActiveRecord::Base.transaction do
      user = User.find_or_initialize_by(phone: user_info["mobile"]) do |u|
        u.login = "ecoder_#{user_info['mobile']}"
        u.type ='User'
        u.status = User::STATUS_ACTIVE
        u.nickname = user_info['username']
        u.lastname = user_info['username']
      end
      
      if !user.persisted?
        user.mail = user_info["email"] unless user_info["email"].blank? || User.find_by_mail(user_info["email"])
        user.save!
        user.create_user_extension!
      end

      open_user.user = user
      open_user.save!
      successful_authentication(user)

      redirect_to "/users/#{user.login}/courses"
    end
  rescue Exception => e
    render :json => {code: 500, msg: "#{e.message}"}
  end

  private

  def request_ecloud_authorization
    url = "#{SERVER_URL}/oauth2/authorization?grant_type=authorization_code&client_id=#{CLIENT_ID}&scope=&redirect_uri=&code=#{params[:code]}"
    decode post(url)
  end

  def get_ecloud_user(body)
    res = get("#{SERVER_URL}/user/info?access_token=#{body['access_token']}&userid=#{body['uid']}")
  end

  def get(url)
    uri = URI(url)

    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = url.start_with?('https')
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    request = Net::HTTP::Get.new(uri.request_uri)
    request['Content-Type'] = 'application/json'
    request['Accept'] = 'application/json'
    response = http.request(request)

    response.body
  end

  def post(url)
    uri = URI(url)

    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = url.start_with?('https')
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    request = Net::HTTP::Post.new(uri.request_uri)
    request['Content-Type'] = 'application/json'
    request['Accept'] = 'application/json'
    response = http.request(request)

    response.body
  end

  def decode(s)
    begin
      obj = ActiveSupport::JSON.decode(s)
    rescue ActiveSupport::JSON.parse_error
      logger.error("Attempted to decode invalid JSON: #{s}")
    end
  end

  private
  def eloud_params
    return {applyno: params['applyno'], ecordercode: params['ecordercode'], opttype: params['opttype'],
            trial: params['trial'], bossorderid: params['bossorderid'], custid: params['custid'], custtype: params['custtype'],
            custcode: params['custcode'], registersource: params['registersource'], custname: params['custname'],
            userid: params['userid'], username: params['username'], useralias: params['useralias'], mobile: params['mobile'],
            email: params['email'], productcode: params['productcode'], begintime: params['begintime'],
            endtime: params['endtime']}
  end

  # 新增套餐
  def create_service services, ecloud_id
    services.each do |service|
      ese = EcloudService.create!(opttype: service['opttype'], code: service['code'], begintime: service['begintime'],
                                  endtime: service['endtime'], ecloud_id: ecloud_id)
      if service['serviceparas'].present?
        create_serviceparas(service['serviceparas'].first, ese.id)
      end
    end
  end

  def create_serviceparas params_serviceparas, ese_id
    if params_serviceparas.present?
      EcloudServieceServicepara.create(key: params_serviceparas['key'], value: params_serviceparas['value'], ecloud_service_id: ese_id)
    end
  end

  def create_product_params params, ecloud_id
    params.each do |p|
      EcloudProductpara.create(key: p['key'], value: p['value'], ecloud_id: ecloud_id)
    end
  end

  def check_sign_key
    sign = sign(params['timestamp'])
    if sign != params['sign']
      render :json => {code: 501, msg: "sign的值错误"}
      return
    end
  end

  def save_para
    EcloudLog.create(url: request.url, para_value: params, applyno: params['applyno'], custid: params['custid'],
                     custcode: params['custcode'], userid: params['userid'], username: params['username'])
  end

end
