# this is not a jam session - this is an 'auth session'
class SessionsController < ApplicationController

  before_filter :api_signed_in_user, only: :paypal_express_checkout

  layout "web"

  def signin
    @login_error = false
    @sso = params[:sso]
    @send_back_to = request.headers['REFERER']
    params[:send_back_to] = @send_back_to

    if current_user
      # send them on their way
      complete_sign_in(current_user)
      return
    end

    render :layout => "landing"
  end

  def create
    email = params[:session][:email]
    password = params[:session][:password]
    email.strip! if email
    password.strip! if password

    user = User.authenticate(email, password)

    if user.nil?
      @login_error = true
      @sso = params[:sso]
      @send_back_to = params[:send_back_to]
      render 'signin', :layout => "landing"
    else

      if jkclient_agent?
        user.update_progression_field(:first_ran_client_at)
      end

      @session_only_cookie = !jkclient_agent? && !params[:user].nil? && 0 == params[:user][:remember_me].to_i
      complete_sign_in user
    end
  end

  def paypal_express_checkout
    # should get 'token' and 'PayerID' on success

    # on failure, cancel=1

    if params[:cancel] == '1' || params[:cancel] == 1
      redirect_to params[:path] ? params[:path] : '/client#/jamtrack'
      return
    end

    authorization = current_user.paypal_auth
    if authorization
      authorization.delete
      authorization = nil
    end

    # Always make and save a new authorization. This is because they expire, and honestly there's no cost
    # to just making and saving it.

    user_auth_hash = {
        :provider => 'paypal',
        :uid => params[:PayerID],
        :token => params[:token],
        :refresh_token => nil,
        :token_expiration => 3.hours.from_now, # according to paypal docs, a token is good for 3 hours
        :secret => nil
    }

    # delete existing authorization if exists; useful if N users sharing same paypal:
    authorization = UserAuthorization.find_by_provider_and_uid(user_auth_hash[:provider], user_auth_hash[:uid])
    if authorization
      puts "deleting existing paypal authorization"
      authorization.delete
      authorization = nil
    end
    authorization = current_user.user_authorizations.build(user_auth_hash)
    if !authorization.save
      puts "Paypal authorization errors  for user #{current_user.email} #{authorization.errors.inspect}"
      puts "Paypal params: #{params.inspect}"
    end

    redirect_to '/client#/paypal/confirm'
  end

# OAuth docs
# http://net.tutsplus.com/tutorials/ruby/how-to-use-omniauth-to-authenticate-your-users/
  def create_oauth
    puts "OMG"
    auth_hash = request.env['omniauth.auth']
    authorization = UserAuthorization.find_by_provider_and_uid(auth_hash["provider"], auth_hash["uid"])
    if authorization
      # Sign in for a user who has already registered.
      complete_sign_in authorization.user
    else
      # Sign up for a completely new user.
      # First/last name: auth_hash["info"]["first_name"] and auth_hash["info"]["last_name"]
      # token: auth_hash["credentials"]["token"] -- "expires_at"
      #
      # For debugging - to see what all is there:
      # render :text => auth_hash.to_yaml
      #FbGraph.debug!
      token = auth_hash[:credentials][:token]

      # FIXME:
      # This should probably be in a transaction somehow, meaning the user 
      # create and the authorization create. Concern is UserManager.new.signup sends
      # an email and whatnot.
      #
      # Also, should we grab their photo from facebook?
      user = UserManager.new.signup(remote_ip: remote_ip(),
                                    first_name: auth_hash[:info][:first_name],
                                    last_name: auth_hash[:info][:last_name],
                                    email: auth_hash[:info][:email],
                                    timezone: current_timezone,
                                    affiliate_referral_id: cookies[:affiliate_visitor])
                              
      # Users who sign up using oauth are presumed to have valid email adddresses.
      user.confirm_email!
      
      auth = user.user_authorizations.build :provider => auth_hash[:provider], 
                                            :uid => auth_hash[:uid], 
                                            :token => auth_hash[:credentials][:token], 
                                            :token_expiration => Time.at(auth_hash[:credentials][:expires_at])
      user.save
      complete_sign_in user
    end
  end


  # https://github.com/intridea/omniauth/wiki/Saving-User-Location
  def oauth_callback

    auth_hash = request.env['omniauth.auth']

    provider = auth_hash[:provider]
    provider = provider.to_s
    provider.strip!

    if provider == 'google_login'

    elsif provider == 'stripe_connect'
      oauth_callback_stripe_connect(auth_hash)
      return
    elsif provider == 'twitter'
      @user_authorization = current_user.build_twitter_authorization(auth_hash)
      if !@user_authorization.save
        # this is a very poorly styled page, but it's better than a server error.
        # the only reason this happens is because some other account has authed this twitter acct
        render "twitter_oauth_failure"
        return
      end

      redirect_to request.env['omniauth.origin'] || '/'
      return
    elsif provider == 'facebook'
      fb_uid = auth_hash[:uid]
      token = auth_hash[:credentials][:token]
      token_expiration = Time.at(auth_hash[:credentials][:expires_at])
      first_name = auth_hash[:extra][:raw_info][:first_name]
      last_name = auth_hash[:extra][:raw_info][:last_name]
      email = auth_hash[:extra][:raw_info][:email]
      gender = auth_hash[:extra][:raw_info][:gender]

      fb_signup = FacebookSignup.new
      fb_signup.uid = fb_uid
      fb_signup.token = token
      fb_signup.token_expires_at = token_expiration
      fb_signup.first_name = first_name
      fb_signup.last_name = last_name
      fb_signup.email = email
      if gender == 'male'
        fb_signup.gender = 'M'
      elsif gender == 'female'
        fb_signup.gender = 'F'
      end
      fb_signup.save!

      # see if we can find a SignupHint for a JamTrack; if so, bounce them back to the redeemComplete page to let them know we bought it

      if anonymous_user
        signup_hint = anonymous_user.signup_hint
        if signup_hint && signup_hint.redirect_location
          options = {
              first_name: first_name,
              last_name: last_name,
              email: email,
              terms_of_service: true,
              location: {:country => nil, :state => nil, :city => nil},
              affiliate_referral_id: cookies[:affiliate_visitor],
              origin: origin_cookie,
              timezone: current_timezone
          }

          options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options)

          user = UserManager.new.signup(options)

          if user.errors.any?
            redirect_to signup_hint.redirect_location
            return
          end

          sign_in(user)
          new_user(user, signup_hint)
          redirect_to signup_hint.redirect_location
          return
        else
          redirect_to "#{signup_path}?facebook_signup=#{fb_signup.lookup_id}"
          return
        end
      else
        redirect_to "#{signup_path}?facebook_signup=#{fb_signup.lookup_id}"
        return
      end
    end

    if current_user.nil?
      render :nothing => true, :status => 404
      return
    end

    authorization = UserAuthorization.find_by_provider_and_uid(auth_hash["provider"], auth_hash["uid"])

    # Always make and save a new authorization. This is because they expire, and honestly there's no cost
    # to just making and saving it.

    user_auth_hash = {
      :provider => auth_hash[:provider],
      :uid => auth_hash[:uid], 
      :token => auth_hash[:credentials][:token],
      :refresh_token => auth_hash[:credentials][:refresh_token],
      :token_expiration => Time.at(auth_hash[:credentials][:expires_at]),
      :secret => auth_hash[:credentials][:secret]
    }

    if authorization.nil?

      authorization = current_user.user_authorizations.build(user_auth_hash)
      authorization.save

    else
      authorization.token = auth_hash[:credentials][:token]
      authorization.token_expiration = Time.at(auth_hash[:credentials][:expires_at])
      authorization.save
    end


    render 'oauth_complete', :layout => "landing"
  end

  def oauth_callback_stripe_connect(auth_hash)

    if current_user.nil?
      redirect_to '/signin'
      return
    end

    # https://github.com/isaacsanders/omniauth-stripe-connect
    #request.env['omniauth.auth']
=begin
{
  "provider"=>"stripe_connect",
  "uid"=>"<STRIPE_USER_ID>",
  "info"=> {
    "scope"=>"read_write", # or "read_only"
    "livemode"=>false,
    "stripe_publishable_key"=>"<STRIPE_PUBLISHABLE_KEY>",
  },
  "credentials"=> {
    "token"=>"<STRIPE_ACCESS_TOKEN>",
    "expires"=>false
  },
  "extra"=> {
    "raw_info"=> {
      "token_type"=>"bearer",
      "stripe_user_id"=>"<STRIPE_USER_ID>",
      "scope"=>"read_only",
      "stripe_publishable_key"=>"<STRIPE_PUBLISHABLE_KEY>",
      "livemode"=>false
    }
  }
}
=end


    # puts "AUTH HASH #{auth_hash.inspect}"
    # AUTH HASH #<OmniAuth::AuthHash credentials=#<OmniAuth::AuthHash expires=false token="sk_test_TU9lDNHpIyJdFAkWtuerfZUM">
    # extra=#<OmniAuth::AuthHash raw_info=#<OmniAuth::AuthHash livemode=false scope="read_write" stripe_publishable_key="pk_test_dyrB3YtkZRSJiQKFrDxBz7pu" stripe_user_id="acct_17dIjBCHBELYys1s" token_type="bearer">>
    # info=#<OmniAuth::AuthHash::InfoHash livemode=false scope="read_write" stripe_publishable_key="pk_test_dyrB3YtkZRSJiQKFrDxBz7pu"> provider="stripe_connect" uid="acct_17dIjBCHBELYys1s">
    authorization = UserAuthorization.find_by_provider_and_uid(auth_hash["provider"], auth_hash["uid"])

    # Always make and save a new authorization. This is because they expire, and honestly there's no cost
    # to just making and saving it.


    user_auth_hash = {
        :provider => auth_hash[:provider],
        :uid => auth_hash[:uid],
        :token => auth_hash[:credentials][:token],
        :refresh_token => auth_hash[:credentials][:refresh_token],
        :token_expiration => auth_hash[:credentials][:expires],
        :secret => auth_hash[:credentials][:secret]
    }

    # 'false' just means really far into the future
    if !user_auth_hash[:token_expiration]
      user_auth_hash[:token_expiration] = Date.new(2050, 1, 1)
    else
      user_auth_hash[:token_expiration] = Time.at(user_auth_hash[:token_expiration])
    end

    if authorization.nil?
      authorization = current_user.user_authorizations.build(user_auth_hash)
      authorization.save
    else
      authorization.token = auth_hash[:credentials][:token]
      authorization.token_expiration = Date.new(2050, 1, 1)
      authorization.save
    end


    # request.env['omniauth.origin']
    redirect_to SignupHint.most_recent_redirect(current_user, '/client#/jamclass',{"stripe-success" => "true"})
  end

  def has_google_auth
    render :json =>  {has_google_auth: (!!current_user && !!UserAuthorization.google_auth(current_user).first)}
  end

  def passthrough
    if params['stoken']
      # should be a remember_me cookie. log them in and redirect
      user = User.find_by_remember_token(params['stoken'])
      if !user.nil?
        sign_in user
      end
    end
    redirect_after_signin('/')
  end

  def redirect_after_signin(default)
    redirect_to(params['redirect-to'].blank? ? default : params['redirect-to'])
  end

  def redirect_to_forums_after_signin
    redirect_to("#{Rails.application.config.vanilla_login_url}?client_id=#{Rails.application.config.vanilla_client_id}&Target=#{ERB::Util.url_encode(params[:send_back_to].blank? ? '/' : params[:send_back_to])}")
  end

  def redirect_to_support_after_signin(user)
    # generate multipass token and sign it
    multipass = DeskMultipass.new(user)
    callback_url = Rails.application.config.multipass_callback_url
    redirect_to "#{callback_url}?multipass=#{multipass.token}&signature=#{multipass.signature}"
  end


  def destroy
    # earlier, code here would delete the connection using client_id  from cookies
    # however, we should never try to delete the client_id cookie (make it as permanent as possible)
    # also, because the client will stop heartbeating and close the connection to gateway,
    # in any case the server will notice after 10 seconds that the user is gone.
    # if we really want someone to know right away that the client is gone, then just make sure the client calls
    # leave session before it calls delete (VRFS-617 should solve that)
    sign_out
    redirect_to client_url
  end

  def failure

    strategy = params['strategy']

    if strategy == 'stripe_connect'

      puts env['omniauth.error.type']
      redirect_to SignupHint.most_recent_redirect(current_user, '/client#/jamclass', {"stripe-success" => "false"})
      return
    end
    redirect_to request.query_parameters['origin'] || '/'
  end

  def connection_state
    if (defined?(TEST_CONNECT_STATES) && TEST_CONNECT_STATES) || 'development'==Rails.env
      @prefix = defined?(TEST_CONNECT_STATE_JS_LOG_PREFIX) ? TEST_CONNECT_STATE_JS_LOG_PREFIX : '*** '
      render('connection_state', :layout => 'client') && return
    end
    render :nothing => true, :status => 404
  end

end
