require 'jam_ruby/recurly_client'
class ApiRecurlyController < ApiController
  before_filter :api_signed_in_user, :except => [:create_account]
  before_filter :create_client
  before_filter :ip_blacklist, :only => [:place_order]
  before_filter :user_blacklist, :only => [:place_order]


  respond_to :json

  # create Recurly account
  def create_account

    billing_info = params[:billing_info]
    shipping_info = params[:shipping_info]
    # should we let the user reuse this card next time?
    reuse_card_next_time = params[:reuse_card_next_time] == "true"
    # should we update the card info, or use what's on file this time?
    reuse_card_this_time = params[:reuse_card_this_time] == "true"
    # terms of service accepted?
    terms_of_service = params[:terms_of_service] == "true"

    if billing_info &&  Rails.application.config.remove_whitespace_credit_card
      number = billing_info[:number]
      billing_info[:number] = number.gsub(/\s+/, "") if number
    end

    if current_user
      # keep reuse card up-to-date
      User.where(id: current_user.id).update_all(reuse_card: params[:reuse_card_next_time])
    else

      options = {
          first_name: billing_info[:first_name],
          last_name: billing_info[:last_name],
          email: params[:email],
          password: params[:password],
          password_confirmation: params[:password],
          terms_of_service: terms_of_service,
          location: {:country => billing_info[:country], :state => billing_info[:state], :city => billing_info[:city]},
          reuse_card: reuse_card_next_time,
          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?
        # render any @user.errors on error
        respond_with_model(user)
        return
      else
        sign_in user
      end
    end

    begin
      billing_info[:ip_address] = request.remote_ip if billing_info
      if reuse_card_this_time
        # do not attempt to update any billing/shipping info unless the user re-inputs their info!
        @account = @client.get_account(current_user)
      else
        @account = @client.find_or_create_account(current_user, billing_info)
      end

      render :json => account_json(@account)
    rescue RecurlyClientError => x
      render json: {:message => x.inspect, errors: x.errors}, :status => 404
    end
  end

  def delete_account
    @client.delete_account(current_user)
    render json: {}, status: 200
  rescue RecurlyClientError => x
    render json: {:message => x.inspect, errors: x.errors}, :status => 404
  end

  # get Recurly account
  def get_account
    @account = @client.get_account(current_user)

    render :json => account_json(@account)
  rescue RecurlyClientError => e
    render json: {message: x.inspect, errors: x.errors}, :status => 404
  end

  # get Recurly payment history
  def payment_history
    @payments=@client.payment_history(current_user, params)
    render :json => {payments: @payments}
  rescue RecurlyClientError => x
    puts "Recurly error #{current_user.email}, #{x}"
    render json: {message: x.inspect, errors: x.errors}, :status => 404
  end

  def invoice_history
    @invoices, account= @client.invoice_history(current_user, params)
    past_due = account && account.state == 'past_due'

    render :json => {entries: @invoices, past_due: past_due}
  rescue RecurlyClientError => x
    puts "Recurly error #{current_user.email}, #{x}"
    render json: {message: x.inspect, errors: x.errors}, :status => 404
  end

  # update Recurly account
  def update_account
    @account=@client.update_account(current_user, params[:billing_info])
    render :json => account_json(@account)
  rescue RecurlyClientError => x
    render json: {message: x.inspect, errors: x.errors}, :status => 404
  end

  # get Billing Information
  def billing_info
    @account = @client.get_account(current_user)
    if @account
      render :json => account_json(@account)
    else
      render :json => {}, :status => 404
    end
  rescue RecurlyClientError => x
    render json: {message: x.inspect, errors: x.errors}, :status => 404
  end

  # update Billing Information
  def update_billing_info
    @account = @client.update_billing_info(current_user, params[:billing_info])
    render :json => account_json(@account)
  rescue RecurlyClientError => x
    render json: {message: x.inspect, errors: x.errors}, :status => 404
  end

  def update_payment
    begin
      recurly_token = params[:recurly_token]
      account = @client.find_or_create_account(current_user, nil, recurly_token)
      @client.update_billing_info_from_token(current_user, account, recurly_token)
      current_user.update_attribute(:stored_credit_card, true)
      past_due = account && account.has_past_due_invoice
      subscription = nil

      plan_code = current_user.desired_plan_code
      result, subscription, account = @client.handle_create_subscription(current_user, plan_code, account)
      has_billing_info = !account.nil? && !account[:billing_info].nil?
      render :json => {
                 past_due: past_due,
                 subscription: subscription, has_billing_info: has_billing_info,
                        plan_code: current_user.subscription_plan_code,
                        desired_plan_code: current_user.desired_plan_code,
                        admin_override_plan_code: current_user.admin_override_plan_code,
                        admin_override_ends_at: current_user.admin_override_ends_at,
                        in_trial: !current_user.subscription_trial_ended?,
                        trial_ends_at: current_user.subscription_trial_ends_at,
                        subscription_rules: current_user.subscription_rules
             }, :status => 200
    rescue RecurlyClientError => x
      render json: {:message => x.inspect, errors: x.errors}, :status => 404
    end
  end
  def create_subscription
    begin
      sale = Sale.purchase_subscription(current_user, params[:recurly_token], params[:plan_code])
      subscription = Recurly::Subscription.find(current_user.recurly_subscription_id)
      render :json => subscription.to_json
    rescue RecurlyClientError => x
      render json: {:message => x.inspect, errors: x.errors}, :status => 404
    end
  end

  def get_subscription
    subscription, account = @client.find_subscription(current_user)
    past_due = account && account.has_past_due_invoice
    has_billing_info = !account.nil? && !account[:billing_info].nil?
    render :json => {
               past_due: past_due,
               subscription: subscription, has_billing_info: has_billing_info,
               plan_code: current_user.subscription_plan_code,
               desired_plan_code: current_user.desired_plan_code,
               admin_override_plan_code: current_user.admin_override_plan_code,
               admin_override_ends_at: current_user.admin_override_ends_at,
               in_trial: !current_user.subscription_trial_ended?,
               trial_ends_at: current_user.subscription_trial_ends_at,
               subscription_rules: current_user.subscription_rules,
           }, :status => 200
  end


  def cancel_subscription
    begin
      @client.cancel_subscription(current_user.recurly_subscription_id)
      subscription = @client.find_subscription(current_user)

      if subscription
        render :json => subscription.to_json
      else
        render :json => {}
      end
    rescue RecurlyClientError => x
      render json: {:message => x.inspect, errors: x.errors}, :status => 404
    end
  end

  def change_subscription_plan
    begin
      plan_code = params[:plan_code]
      if plan_code == ''
        plan_code = nil
      end

      result, subscription, account = @client.update_desired_subscription(current_user, plan_code)
      has_billing_info = !account.nil? && !account[:billing_info].nil?
      past_due = account && account.has_past_due_invoice
      if !result
        render json: {:message => "No change made to plan"}, :status => 422
      else
        render :json => {
                   past_due: past_due,
                   subscription:subscription,
                   has_billing_info: has_billing_info,
                   plan_code: current_user.subscription_plan_code,
                   desired_plan_code: current_user.desired_plan_code,
                   admin_override_plan_code: current_user.admin_override_plan_code,
                   admin_override_ends_at: current_user.admin_override_ends_at,
                   in_trial: !current_user.subscription_trial_ended?,
                   trial_ends_at: current_user.subscription_trial_ends_at,
                   subscription_rules: current_user.subscription_rules
               }
      end
    rescue RecurlyClientError => x
      render json: {:message => x.inspect, errors: x.errors}, :status => 404
    end
  end

  def list_invoices
    begin
      account = @client.get_account(current_user)

      if account.nil?
        render json:[], :status => 200
      else
        return @client.list_invoices(current_user)
      end

    end
  end

  def change_subscription_payment
    begin
      @client.change_subscription_payment(current_user.recurly_subscription_id, params[:recurly_token], params[:billing_info])
      subscription = Recurly::Subscription.find(current_user.recurly_subscription_id)
      render :json => subscription.to_json
    rescue RecurlyClientError => x
      render json: {:message => x.inspect, errors: x.errors}, :status => 404
    end
  end

  def place_order
    error=nil
    response = {jam_tracks: [], gift_cards: []}

    #if Sale.is_mixed(current_user.shopping_carts)
    #  msg = "has free and non-free items. Try removing non-free items."
    #  render json: {message: "Cart " + msg, errors: {cart: [msg]}}, :status => 404
    #  return
    #end

    sales = Sale.place_order(current_user, current_user.shopping_carts)


    sales.each do |sale|
      sale.sale_line_items.each do |line_item|
        if line_item.is_jam_track?
          jam_track = line_item.product
          jam_track_right = jam_track.right_for_user(current_user)
          response[:jam_tracks] << {name: jam_track.name, id: jam_track.id, jam_track_right_id: jam_track_right.id, version: jam_track.version}
        elsif line_item.is_gift_card?
          gift_card = line_item.product
          response[:gift_cards] << {name: gift_card.name, id: gift_card.id}
        else
          raise 'unknown sale line item type: ' + line_item.product_type
        end
      end
    end

    if error
      render json: {errors: {message: error}}, :status => 404
    else
      set_purchased_jamtrack_cookie
      render :json => response, :status => 200
    end
  rescue RecurlyClientError => x
    render json: {message: x.inspect, errors: x.errors}, :status => 404
  end

  private
  def create_client
    @client = RecurlyClient.new
  end

  def account_json(account)

    billing_info = account.billing_info.nil? ? nil : {
        :first_name => account.billing_info.first_name,
        :last_name => account.billing_info.last_name,
        :address1 => account.billing_info.address1,
        :address2 => account.billing_info.address2,
        :city => account.billing_info.city,
        :state => account.billing_info.state,
        :zip => account.billing_info.zip,
        :country => account.billing_info.country,
        :last_four => account.billing_info.last_four
    }

    {
        billing_info: billing_info
    }
  end

end # class