#encoding: utf-8
require 'base64'
class TrainingsController < ApplicationController
  wechat_responder

  skip_before_filter :verify_signature, only: [:show, :create, :test]

  ROOT_URL = ENV["wechat_url"] || "#{Setting.protocol}://#{Setting.host_name}"

  before_filter :authenticate, except: [:auth, :auth_callback, :pay_callback]
  before_filter :find_training, only: [:show, :test]

  before_filter :valid_training, only: [:pay, :result, :pay_js]

  layout 'base_trainings'


  TAG_ID = 'bigdata_hnjcxy_2019'

  def show
    @training = current_training

    url = nil
    if @training && !@training.pay?
      url = enroll_training_path(id: TAG_ID)
    elsif @training && @training.pay?
      url = result_training_path(id: TAG_ID)
    else
      url = enroll_training_path(id: TAG_ID)
    end

    redirect_to url
  end

  def enroll
    @training = current_training || Training.new
  end



  def pay
    _pay_params

    @training = current_training

    # 防止重复支付,对于已支付过的,不应该再到这个页来
    if @training.payed?
      redirect_to result_training_path(id: TAG_ID)
      return
    end

    @training.training_payinfo ||= TrainingPayinfo.new

  end

  def pay_callback
    # {"xml"=>{"appid"=>"wx8c5bd82a8a584cf6", "bank_type"=>"CFT", "cash_fee"=>"1", "fee_type"=>"CNY",
    # "is_subscribe"=>"Y", "mch_id"=>"1516303811", "nonce_str"=>"c462b28237d5e70261c3171319d86bf5",
    # "openid"=>"o5fSc02LFi7LEGCk_ckp6YbegFWs", "out_trade_no"=>"2018101714093870",
    # "result_code"=>"SUCCESS", "return_code"=>"SUCCESS", "sign"=>"155D16352B5F2287A32B3121175D8B0B",
    # "time_end"=>"20181017140944", "total_fee"=>"1", "trade_type"=>"JSAPI",
    # "transaction_id"=>"4200000166201810174468792543"}}
    logger.info "pay_callback #{params}"
    unless params["xml"]
      logger.error "pay_callback error: not found xml"
    end

    pay = WechatPay.find_by_out_trade_no(params[:xml]["out_trade_no"])
    pay.update_attributes!(params[:xml])

    training = Training.find(pay.training_id)
    training_payinfo = training.training_payinfo
    training_payinfo.update_attributes!(status: TrainingPayinfo::Status_Payed,
                                        out_trade_no: pay.out_trade_no)

    # 报名成功发送短信
=begin
    begin
      Trustie::Sms.send(mobile: training.phone,
                        send_type: "training_pay",
                        user_name: training.name)
    rescue => e
      logger.error("pay_callback 短信发送失败: #{e}")
    end
=end

    render :xml => '' '
    <xml>
      <return_code><![CDATA[SUCCESS]]></return_code>
      <return_msg><![CDATA[OK]]></return_msg>
    </xml>
    ' ''
  end

  def result
    _pay_params
    @training = current_training
  end


  def create
    @training = current_training || Training.new(params)
    @training.training_type = Training::Training_Type
    @training.openid = session[:wechat_open_id]
    @training.save!

    redirect_to pay_training_path(id: TAG_ID)
  end


  def update
    @training = current_training
    unless @training
      render_404
      return
    end

    @training.update_attributes(params)
    redirect_to pay_training_path(id: TAG_ID)
  end


  # 对应两种情况的信息提交
  # 1. 稍后支付
  # 2. 立刻支付
  #    采用ajax调用方式,返回支付参数
  def update_payinfo
    @training = current_training
    unless @training
      render_404
      return
    end

    _pay_params

    attachment = nil
    if params[:image]
      attachment = Attachment.create!(file: params[:image], author: User.first)
    end

    #修改以前的订单信息
    training_info = @training.training_payinfo
    if training_info.present?
      training_info.update_attributes(params)
    else
      training_info = TrainingPayinfo.new(params)
    end

    training_info.num = params[:enlistN].to_i
    if training_info.num < 1
      training_info.num = 1
    end

    training_info.fee = (training_info.num  * @pay_fee).to_i

    training_info.attachment = attachment if attachment.present?

    if training_info.pay_type.to_i == TrainingPayinfo::PayType_Wechat
      training_info.status = TrainingPayinfo::Status_None
    else
      training_info.status = TrainingPayinfo::Status_Wait
    end

    training_info.training_id = @training.id

    training_info.save!

    if params[:js] == 'true'
      _pay_js(training_info.fee)
    else
      redirect_to url = result_training_path(id: TAG_ID)
    end
  end


  ### js function
  def update_picture
    @training = current_training
    js_function_call do
      attachment = Attachment.create!(file: params[:image], author: User.first)
      training_payinfo = @training.training_payinfo
      training_payinfo.attachment = attachment
      training_payinfo.save!
      render json: {status: 0}
    end
  end


  def pay_js
    @training = current_training
    _pay_js(@training.training_payinfo.fee)
  end

  #js获取支付参数
  def _pay_js(fee)
    @training = current_training
    js_function_call do
      out_trade_no = Wechat.pay.gen_trade_no
      #@training.training_payinfo.update_attribute(:out_trade_no, out_trade_no)
      #
      #
      # 写入wechat_pay付费表
      WechatPay.create!(training_id: @training.id, out_trade_no: out_trade_no)
      render json: {status: 0, data: unifiedorder(out_trade_no, fee)}
    end
  end


  # 用于权限跳转
  def auth
    state = params[:state]
    url = "#{ROOT_URL}/trainings/auth_callback"
    authorize_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{url}&response_type=code&scope=snsapi_base&state=#{state}&connect_redirect=1#wechat_redirect"
    redirect_to authorize_url
  end

  def auth_callback
    path = Base64.urlsafe_decode64(params[:state])
    open_id = get_openid_from_code(params[:code])
    unless open_id
      render 'wechats/open_wechat', layout: nil and return
    end


    session[:wechat_open_id] = open_id

    # 考虑状态
    # 1. 无记录或未支付
    # 2. 已填写未付款
    #
    @training = current_training

    url = ''
    if !@training
      url = training_path(id: TAG_ID)
    elsif !@training.pay?
      url = enroll_training_path(id: TAG_ID)
    else
      url = result_training_path(id: TAG_ID)
    end

    redirect_to url

  end

  def test

  end

  private
  def _pay_params
    @pay_fee = Redmine::Configuration['training_fee'].to_f || 5000
  end

  def authenticate
    if Rails.env.development?
      # session[:wechat_open_id] = "o5fSc0607iR3rp4-h_VnuBTp8CiM"
    end

    unless session[:wechat_open_id].present?
      redirect_to auth_trainings_path
    end
  end

  def find_training
    if params[:id] == TAG_ID
      @training = current_training
    else
      render_404
    end
  end

  def current_training
    Training.where(openid: session[:wechat_open_id], training_type: Training::Training_Type).first
  end

  def valid_training
    unless current_training
      redirect_to training_path(id: TAG_ID)
    end
  end


  private

  def js_function_call
    begin
      yield if block_given?
    rescue => e
      render json: {status: 1, msg: e.message}
    end
  end

  def client_ip
    request.headers['X-Real-IP'] || request.remote_ip || "127.0.0.1"
  end

  def get_openid_from_code(code)
    openid = session[:wechat_open_id]
    unless openid
      if code
        #不能联系调两次web_access_token 否则会提示请在微信客户端打开次链接
        info = wechat.web_access_token(code)
        openid = info["openid"]
        access_token = info["access_token"]
        if access_token
          session[:access_token] = access_token
        end
        refresh_token = info["refresh_token"]
        if refresh_token
          session[:refresh_token] = refresh_token
        end
      end
    end

    if openid
      session[:wechat_open_id] = openid
    end

    return openid
  end


  def unifiedorder(out_trade_no, fee)
    @config = {}

    output = Wechat.pay.unifiedorder('湖南警察学院大数据培训会-报名费',
                                     (fee * 100).to_i,
                                     session[:wechat_open_id],
                                     client_ip,
                                     out_trade_no)
    data = output.fetch("xml")
    if data.nil?
      raise "获取微信统一单错误"
    end

    if data["return_code"] != 'SUCCESS'
      raise "获取微信统一单错误:#{data["return_msg"]}"
    end


    @config[:appid] = data["appid"]
    @config[:nonce] = data["nonce_str"]
    @config[:prepay_id] = data["prepay_id"]
    @config[:time] = Time.now.to_i


    info = {
        appId: @config[:appid],
        timeStamp: @config[:time],
        nonceStr: @config[:nonce],
        package: "prepay_id=#{@config[:prepay_id]}",
        signType: 'MD5'
    }
    @config[:sign] = Wechat.pay.sign(info)

    @config
  end

end