#coding=utf-8
class WechatsController < ActionController::Base
  wechat_responder

  include ApplicationHelper
  ROOT_URL = ENV["wechat_url"]  || "#{Setting.protocol}://#{Setting.host_name}"
  #ROOT_URL = "http://www.trustie.net"
  # default text responder when no other match
  on :text do |request, content|
      #邀请码
    # if join_class_request(request)
    #   sendBindClass(request, {invite_code: content})
    # elsif join_project_request(request)
    #   sendBindProject(request, {invite_code: content})
    # else
      request.reply.text "您的意见已收到，非常感谢~ \n更多问题可以通过以下方式联系我们：\n官方QQ群：173184401\n我们会认真聆听您的意见和建议。"
    # end
  end

  # When receive 'help', will trigger this responder
  on :text, with: 'help' do |request|
    request.reply.text 'help content'
  end

  # When receive '<n>news', will match and will got count as <n> as parameter
  on :text, with: /^(\d+) news$/ do |request, count|
    # Wechat article can only contain max 10 items, large than 10 will dropped.
    news = (1..count.to_i).each_with_object([]) { |n, memo| memo << { title: 'News title', content: "No. #{n} news content" } }
    request.reply.news(news) do |article, n, index| # article is return object
      article.item title: "#{index} #{n[:title]}", description: n[:content], pic_url: 'http://www.baidu.com/img/bdlogo.gif', url: 'http://www.baidu.com/'
    end
  end

  on :event, with: 'subscribe' do |request|
    default_msg(request)
  end

  # When unsubscribe user scan qrcode qrscene_xxxxxx to subscribe in public account
  # notice user will subscribe public account at same time, so wechat won't trigger subscribe event any more
  on :scan, with: 'qrscene_xxxxxx' do |request, ticket|
    request.reply.text "Unsubscribe user #{request[:FromUserName]} Ticket #{ticket}"
  end

  # When subscribe user scan scene_id in public account
  on :scan, with: 'scene_id' do |request, ticket|
    sendBindClass(request, {ticket: ticket})
  end

  # When no any on :scan responder can match subscribe user scaned scene_id
  on :event, with: 'scan' do |request|
    if request[:EventKey].present?
      checkTicket(request, {ticket: request[:Ticket]})
    end
  end

  # When enterprise user press menu BINDING_QR_CODE and success to scan bar code
  on :scan, with: 'BINDING_QR_CODE' do |request, scan_result, scan_type|
    request.reply.text "User #{request[:FromUserName]} ScanResult #{scan_result} ScanType #{scan_type}"
  end

  # Except QR code, wechat can also scan CODE_39 bar code in enterprise account
  on :scan, with: 'BINDING_BARCODE' do |message, scan_result|
    if scan_result.start_with? 'CODE_39,'
      message.reply.text "User: #{message[:FromUserName]} scan barcode, result is #{scan_result.split(',')[1]}"
    end
  end

  # When user click the menu button
  on :click, with: 'BOOK_LUNCH' do |request, key|
    request.reply.text "User: #{request[:FromUserName]} click #{key}"
  end

  on :click, with: 'DEV' do |request, key|
    uw = user_binded?(request[:FromUserName])
    unless uw
      sendBind(request)
    else
      request.reply.text "此功能正在开发中，很快就会上线，谢谢！"
    end
  end
  # When user view URL in the menu button
  on :view, with: 'http://wechat.somewhere.com/view_url' do |request, view|
    request.reply.text "#{request[:FromUserName]} view #{view}"
  end

  # When user sent the imsage
  on :image do |request|
    request.reply.image(request[:MediaId]) # Echo the sent image to user
  end

  # When user sent the voice
  on :voice do |request|
    request.reply.voice(request[:MediaId]) # Echo the sent voice to user
  end

  # When user sent the video
  on :video do |request|
    nickname = wechat.user(request[:FromUserName])['nickname'] # Call wechat api to get sender nickname
    request.reply.video(request[:MediaId], title: 'Echo', description: "Got #{nickname} sent video") # Echo the sent video to user
  end

  # When user sent location
  on :location do |request|
    request.reply.text("Latitude: #{message[:Latitude]} Longitude: #{message[:Longitude]} Precision: #{message[:Precision]}")
  end

  on :event, with: 'unsubscribe' do |request|
    request.reply.success # user can not receive this message
  end

  # When user enter the app / agent app
  on :event, with: 'enter_agent' do |request|
    request.reply.text "#{request[:FromUserName]} enter agent app now"
  end

  # When batch job create/update user (incremental) finished.
  on :batch_job, with: 'sync_user' do |request, batch_job|
    request.reply.text "sync_user job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
  end

  # When batch job replace user (full sync) finished.
  on :batch_job, with: 'replace_user' do |request, batch_job|
    request.reply.text "replace_user job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
  end

  # When batch job invent user finished.
  on :batch_job, with: 'invite_user' do |request, batch_job|
    request.reply.text "invite_user job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
  end

  # When batch job replace department (full sync) finished.
  on :batch_job, with: 'replace_party' do |request, batch_job|
    request.reply.text "replace_party job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
  end

  # Any not match above will fail to below
  on :fallback, respond: 'fallback message'

  on :click, with: 'FEEDBACK' do |request, key|
    request.reply.text "如有问题反馈，请您：\n1、直接切换至输入框，发微信给我们。\n2、加入QQ群：173184401，我们直接互动。\n欢迎大家积极反馈，谢谢啦！"
  end

  on :click, with: 'MY_NEWS' do |request, key|
    default_msg(request)
  end

  on :click, with: 'PROJECT' do |request, key|
    request.reply.text "该功能将在近日开放，敬请期待！"
  end

  on :click, with: 'JOIN_PROJECT' do |request, key|
    # request.reply.text "该功能将在近日开放，敬请期待！"
    uw = user_binded?(request[:FromUserName])
    unless uw
      sendBind(request)
    else
      request.reply.text "请直接回复6位项目邀请码\n(不区分大小写):"
    end
  end

  on :click, with: 'JOIN_CLASS' do |request, key|
    uw = user_binded?(request[:FromUserName])
      unless uw
        sendBind(request)
    else
      request.reply.text "请直接回复5位班级邀请码\n(不区分大小写):"
    end
  end

  on :click, with: 'UNBIND' do |request, key|
    uw = user_binded?(request[:FromUserName])
    unless uw
      request.reply.text "您还未绑定帐号"
    else
      #解除绑定
      us = UsersService.new
      us.wechat_unbind uw

      tmpurl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{ROOT_URL+'/wechat/user_activities'}&response_type=code&scope=snsapi_base&state=login&connect_redirect=1#wechat_redirect"
      news = (1..1).each_with_object([]) { |n, memo| memo << { title: '重新绑定提醒',
                                                               content: "尊敬的用户，您已解除绑定。\n解除时间：#{format_time(Time.now)}\n点击进入重新绑定！"} }
      request.reply.news(news) do |article, n, index| # article is return object
        url = tmpurl
        article.item title: "#{n[:title]}",
                     description: n[:content],
                     url: url
      end
    end
  end

  def join_class_request(request)
    openid = request[:FromUserName]
    wl = WechatLog.where("openid = '#{openid}' and request_raw like '%\"Event\":\"click\"%'").order('id desc').first
    wl && JSON(wl.request_raw)["EventKey"] == 'JOIN_CLASS'
  end

  def join_project_request(request)
    openid = request[:FromUserName]
    wl = WechatLog.where("openid = '#{openid}' and request_raw like '%\"Event\":\"click\"%'").order('id desc').first
    wl && JSON(wl.request_raw)["EventKey"] == 'JOIN_PROJECT'
  end

  def sendBindClass(request, params)
    begin
      uw = user_binded?(request[:FromUserName])
      if !uw
        return sendBind(request)
      else
        return join_class(params, uw.user, request)
      end
    rescue => e
      logger.error e.inspect
      logger.error e.backtrace.join("\n")
      return request.reply.text e
    end
  end

  def sendBindProject(request, params)
    begin
      uw = user_binded?(request[:FromUserName])
      if !uw
        return sendBind(request)
      else
        return join_project(params, uw.user, request)
      end
    rescue => e
      logger.error e.inspect
      logger.error e.backtrace.join("\n")
      return request.reply.text e
    end
  end

  def checkTicket(request,params)
    begin
      uw = user_binded?(request[:FromUserName])
      if !uw
        return sendBind(request)
      end

      course = nil
      course = Course.where(qrcode: params[:ticket]).first if params[:ticket]
      course = Course.where(invite_code: params[:invite_code]).first if params[:invite_code]

      if course
        return join_class(params, uw.user, request)
      else
        project = nil
        project = Project.where(qrcode: params[:ticket]).first if params[:ticket]
        project = Project.where(invite_code: params[:invite_code]).first if params[:invite_code]
        if project
          return join_project(params, uw.user, request)
        end
      end

      raise "该二维码已失效"

    rescue => e
      logger.error e.inspect
      logger.error e.backtrace.join("\n")
      return request.reply.text e
    end


  end

  def default_msg(request)
    uw = user_binded?(request[:FromUserName])
    if uw && uw.user
      request.reply.text "欢迎回来, #{uw.user.show_name}"
    else
      sendBind(request)
    end
  end

  def sendBind(request)
    tmpurl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{ROOT_URL+'/wechat/user_activities'}&response_type=code&scope=snsapi_base&state=login&connect_redirect=1#wechat_redirect"
    logger.info "tmpurl!!!!!!!!!!!!!!"
    logger.info tmpurl
    news = (1..1).each_with_object([]) { |n, memo| memo << { title: '绑定登录', content: "欢迎使用Trustie创新实践服务平台！
在这里您可以随时了解您的课程和项目动态，随时点赞和回复。
我们将会与微信不断结合，为您提供更有价值的服务。

您还未绑定确实的用户，请先绑定，谢谢！" } }
    request.reply.news(news) do |article, n, index| # article is return object
      url = tmpurl
      pic_url = "#{ROOT_URL}/images/weixin_pic.jpg"
      article.item title: "#{n[:title]}",
                   description: n[:content],
                   pic_url: pic_url,
                   url: url
    end
  end

  def join_class(params, user, request)
    course = nil
    course = Course.where(qrcode: params[:ticket]).first if params[:ticket]
    course = Course.where(invite_code: params[:invite_code]).first if params[:invite_code]
    raise "班级不存在，请确认您的邀请码是否输入正确，谢谢！" unless course

    #取出用户角色类型
    role = 10

    cs = CoursesService.new
    status = cs.join_course({invite_code: course.invite_code}, user)
    logger.info status
    if status[:state] != 0
      raise CoursesService::JoinCourseError.message(status[:state])
    end

    news = (1..1).each_with_object([]) { |n, memo| memo << { title: '恭喜您成功加入班级，开始学习吧！',
                                                             content: "课程名称：#{course.syllabus.title}\n班级名称：#{course.name}\n任课老师：#{course.teacher.show_name}\n进入班级，和小伙伴愉快的学习吧！"} }
    return request.reply.news(news) do |article, n, index| # article is return object
      url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{ROOT_URL+'/wechat/user_activities#/class?id='+course.id.to_s}&response_type=code&scope=snsapi_base&state=myclass#wechat_redirect"
      pic_url = "#{ROOT_URL}/images/wechat/class.jpg"
      article.item title: "#{n[:title]}",
                   description: n[:content],
                   pic_url: pic_url,
                   url: url
    end

  end

  def join_project(params, user, request)
    project = nil
    project = Project.where(qrcode: params[:ticket]).first if params[:ticket]
    project = Project.where(invite_code: params[:invite_code]).first if params[:invite_code]
    raise "项目不存在，请确认您的邀请码是否输入正确，谢谢！" unless project

    #取出用户角色类型
    role = 5

    ps = ProjectsService.new
    status = ps.join_project({role:5, invite_code: project.invite_code}, user)
    if status != 0
      raise ProjectsService::JoinProjectError.message(status)
    end

    creator = User.find(project.user_id)

    news = (1..1).each_with_object([]) { |n, memo| memo << { title: '恭喜您成功加入项目，开始研发吧！',
                                                             content: "项目名称：#{project.name}\n发起人：#{creator.show_name}\n进入项目，和小伙伴轻松的研发吧！"} }
    return request.reply.news(news) do |article, n, index| # article is return object
      url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{ROOT_URL+'/wechat/user_activities#/project?id='+project.id.to_s}&response_type=code&scope=snsapi_base&state=myproject#wechat_redirect"
      pic_url = "#{ROOT_URL}/images/wechat/project.jpg"
      article.item title: "#{n[:title]}",
                   description: n[:content],
                   pic_url: pic_url,
                   url: url
    end

  end

  ###  controller method
  module Controllers
    def get_bind
      begin
        code = params[:code] || session[:wechat_code]
        openid = get_openid_from_code(code)

        # raise "无法获取到微信openid" unless openid

        raise "请在微信中关注Trustie创新实践平台后再打开本页面" unless openid

        uw = UserWechat.where(openid: openid).first
        raise "还未绑定trustie帐户" unless (uw && uw.bindtype == 0)
        logger.debug "get_bind ============= #{uw}"

        user = uw.user
        ::ApiKey.delete_all(user_id: user.id)
        key = ::ApiKey.create!(user_id: user.id)

        render :json =>{status: 0, token: key.access_token}
      rescue Exception=>e
        render :json => {status: -1, message: e.message}
      end
    end

    def is_bind
      begin
        code = params[:code] || session[:wechat_code]
        open_id = get_openid_from_code(code)
        raise "还未绑定trustie帐户" unless user_binded?(open_id)
        render :json => {status: 0}
      rescue Exception=>e
        render :json => {status: -1, message: e.message}
      end
    end

    def bind
      begin

        code = params[:code] || session[:wechat_code]
        openid = get_openid_from_code(code)

        # raise "无法获取到openid，请在微信中打开本页面" unless openid
        raise "请在微信中关注Trustie创新实践平台后再打开本页面" unless openid
        raise "此微信号已绑定用户，不能重复绑定" if user_binded?(openid)

        user, last_login_on = User.try_to_login(params[:username], params[:password])
        raise "用户名或密码错误，请重新输入" unless user
        #补全用户信息

        raise "此用户已经绑定过公众号，请换一个帐户试试" if user.user_wechat

        UserWechat.create!(
            openid: openid,
            user: user
        )
        ws = WechatService.new
        ws.binding_succ_notice(user.id, "您已成功绑定Trustie平台！", user.show_name+"("+user.login+")", format_time(Time.now))
        render :json => {status:0, msg: "绑定成功"}
      rescue Exception=>e
        render :json => {status: -1, msg: e.message}
      end
    end

    def login
      session[:wechat_code] = params[:code] if params[:code]
      openid = get_openid_from_code(params[:code])
      @wechat_user = user_binded?(openid)
      render 'wechats/user_activities', layout: nil
    end

   

    def user_activities

      @appid = Wechat.config.appid
      ## sign

      @sign_params = wechat.jsapi_ticket.signature(current_url)

      session[:wechat_code] = params[:code] if params[:code]
      @path = '/'+(params[:state] || '')
      open_id = get_openid_from_code(params[:code]) rescue
      unless open_id
        render 'wechats/open_wechat', layout: nil and return
      end

      logger.info "user_activities!!!!!!!!!!!!!!"
      logger.info params

      #保证下面的redirect_to "/wechat/user_activities##{@path}?id=...不会往下走
      if params[:state] == nil
        return
      end
      
      unless (user_binded?(open_id) || params[:state] == "invite_code" || params[:state] == "project_invite_code" ||  params[:state] == "blog_comment" || params[:state] == "course_notice" || params[:state] == "project_discussion" || params[:state] == "course_discussion" || params[:state] == "homework" || params[:state] == "issues" || params[:state] == "journal_for_message")
        @path = '/login'
      else
        if params[:state] == 'myclass'
          @course_id = params[:id];
        elsif params[:state] == 'myproject'
          @project_id = params[:id];
        end

        session[:wechat_openid] = open_id
        if params[:code]
          if !(params[:state] == "invite_code" || params[:state] == "project_invite_code" ||  params[:state] == "blog_comment" || params[:state] == "course_notice" || params[:state] == "project_discussion" || params[:state] == "course_discussion" || params[:state] == "homework" || params[:state] == "issues" || params[:state] == "journal_for_message")
            uw = user_binded?(open_id)
            if uw
              user = uw.user
              lastname = user.lastname
            end
          end

          if lastname && lastname == ""
            @path = '/edit_userinfo'
          else
            @path = params[:state].split('/')[0]
            useridstr = params[:state].split('/')[1]

            if useridstr
              redirect_to "/wechat/user_activities##{@path}?id=#{params[:id]}&#{useridstr}" and return
            elsif params[:id]
              redirect_to "/wechat/user_activities##{@path}?id=#{params[:id]}" and return
            else
              redirect_to "/wechat/user_activities##{@path}" and return
            end
            # redirect_to "/wechat/user_activities##{@path}?id=#{params[:id]}" and return
          end
        end
      end
      render 'wechats/user_activities', layout: nil
    end


    private
    def get_openid_from_code(code)
      return 'oCnvgvz8R7QheXE-R9Kkr39j8Ndg' if code =='only-for-test'
      openid = session[:wechat_openid]
      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_openid] = openid
      end

      return openid
    end

    def user_binded?(openid)
      uw = UserWechat.where(openid: openid).first
      if uw && uw.bindtype == 0
        uw
      else
        nil
      end
    end

    def current_url
      "#{request.protocol}#{request.host_with_port}#{request.fullpath}"
    end


  end


  include Controllers

end
