require 'spec_helper'

describe ApiUsersController, type: :controller do
  render_views

  let (:user) { FactoryGirl.create(:user) }
  let (:conn) { FactoryGirl.create(:connection, user: user, last_jam_audio_latency: 5) }
  let (:jam_track) { FactoryGirl.create(:jam_track)}


  before(:each) do
    controller.current_user = user
  end

  describe "redeem_giftcard" do
    let!(:gift_card) {FactoryGirl.create(:gift_card)}

    it "can succeed" do
      post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'

      response.should be_success

      user.reload
      gift_card.reload

      user.gift_cards.should eq([gift_card])
      user.gifted_jamtracks.should eq(5)
      gift_card.user.should eq(user)
    end

    it "indicates if you've redeemed it" do
      gift_card.user = user
      gift_card.save!

      post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'

      response.status.should eq(422)
      error_data = JSON.parse(response.body)
      error_data['errors']['gift_card'].should eq(["already redeemed by you"])

      user.reload
      gift_card.reload

      user.gift_cards.should eq([gift_card])
      user.gifted_jamtracks.should eq(5)
      gift_card.user.should eq(user)
    end

    it "indicates if someone else has redeemed it" do
      user2 = FactoryGirl.create(:user)
      gift_card.user = user2
      gift_card.save!

      post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'

      response.status.should eq(422)
      error_data = JSON.parse(response.body)
      error_data['errors']['gift_card'].should eq(["already redeemed by another"])

      user.reload
      gift_card.reload

      user.gift_cards.should eq([])
      user.gifted_jamtracks.should eq(0)
      gift_card.user.should eq(user2)
    end

    it "marks free shopping cart item as free" do
      # sort of a 'do nothing' really
      cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
      cart1.marked_for_redeem.should eq(1)

      post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'

      response.should be_success

      user.reload
      gift_card.reload

      user.gift_cards.should eq([gift_card])
      user.gifted_jamtracks.should eq(5)
      gift_card.user.should eq(user)
      cart1.reload
      cart1.marked_for_redeem.should eq(1)
    end

    it "marks non-free shopping cart item as free" do
      # sort of a 'do nothing' really
      user.has_redeemable_jamtrack = false
      user.save!

      cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
      cart1.marked_for_redeem.should eq(0)

      post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'

      response.should be_success

      user.reload
      gift_card.reload

      user.gift_cards.should eq([gift_card])
      user.gifted_jamtracks.should eq(5)
      gift_card.user.should eq(user)
      cart1.reload
      cart1.marked_for_redeem.should eq(1)
    end

    it "leaves shopping cart alone if too many items in it for size of new gift card" do
      # sort of a 'do nothing' really
      user.has_redeemable_jamtrack = false
      user.save!

      11.times do |i|
        jamtrack = FactoryGirl.create(:jam_track)
        cart1 = ShoppingCart.add_jam_track_to_cart(user, jamtrack)
        cart1.marked_for_redeem.should eq(0)
      end

      post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'

      response.should be_success

      user.reload
      gift_card.reload

      user.gift_cards.should eq([gift_card])
      user.gifted_jamtracks.should eq(5)
      gift_card.user.should eq(user)
      user.shopping_carts.each do |cart|
        cart.marked_for_redeem.should eq(0)
      end
    end
  end

  describe "create" do
    it "successful" do
      email = 'user_create1@jamkazam.com'
      post :create, first_name: 'Seth', last_name: 'Call', email: email, password: 'jam123', terms: true, format: 'json'
      response.should be_success
      found = User.find_by_email(email)
      found.city.should be_nil
      found.state.should be_nil
      found.country.should be_nil
      found.musician.should be true
      found.musician_instruments.count.should be(1)
      found.last_jam_updated_reason.should eq('r')
      found.last_jam_locidispid.should_not be_nil
    end

    it "no first name is OK" do
      email = 'user_create2@jamkazam.com'
      post :create, first_name: nil, last_name: 'Call', email: email, password: 'jam123', terms: true, format: 'json'
      response.status.should eq(201)
    end

    it "no email" do
      email = nil
      post :create, first_name: nil, last_name: 'Call', email: email, password: 'jam123', terms: true, format: 'json'
      response.status.should eq(422)
      error_data = JSON.parse(response.body)
      error_data['errors']['email'].should eq(["can't be blank", "is invalid"])
    end

    it "short password" do
      email = nil
      post :create, first_name: nil, last_name: 'Call', email: email, password: 'jam', terms: true, format: 'json'
      response.status.should eq(422)
      error_data = JSON.parse(response.body)
      error_data['errors']['password'].should eq(["is too short (minimum is 6 characters)"])
    end

    it "no terms" do
      email = 'user_create3@jamkazam.com'
      post :create, first_name: 'Seth', last_name: 'Call', email: email, password: 'jam123', terms: false, format: 'json'
      response.status.should eq(422)
      error_data = JSON.parse(response.body)
      error_data['errors']['terms_of_service'].should eq(["must be accepted"])
    end
  end

  describe "calendars" do
    before :each do
      Calendar.destroy_all
    end

    it "adds calendar via update" do
      cals = [{
        :name=>"Test Cal",
        :description=>"This is a test",
        :start_at=>(Time.now),
        :end_at=>Time.now,
        :trigger_delete=>true,
        :target_uid=>"2112"
      }]
      post :update, id:user.id, calendars: cals, :format=>'json'
      response.should be_success
      user.reload
      user.calendars.should have(1).items
    end
  end

  describe "update mod" do
    it "empty mod" do
      post :update, id:user.id, mods: {}, :format=>'json'
      response.should be_success
      user.reload
      user.mods_json.should == {}
    end

    it "no_show mod" do
      user_id = user.id
      mods = {"no_show" => {"something1" => true}}
      post :update, id:user.id, mods: mods, :format=>'json'
      response.should be_success

      # verify that the user object has the mods data
      user_again = User.find(user_id)
      user_again.mods_json.should == mods

      # verify that the response shows the mods structure
      json = JSON.parse(response.body)
      json["mods"].should == mods
    end
  end

  describe 'site validation' do

    it 'checks valid and invalid site types' do
      site_types = Utils::SITE_TYPES.clone << 'bandcamp-fan'
      site_types.each do |sitetype|
        rec_id = nil
        case sitetype
        when 'url'
          valid, invalid = 'http://jamkazam.com', 'http://jamkazamxxx.com'
        when 'youtube'
          valid, invalid = 'jonathankolyer', 'jonathankolyerxxx'
        when 'facebook'
          valid, invalid = 'jamkazam', 'jamkazamxxxx'
        when 'twitter'
          valid, invalid = 'jamkazam', 'jamkazamxxxx'
        when 'soundcloud'
          valid, invalid = 'zedisdead', 'zedisdeadxxxx'
        when 'reverbnation'
          valid, invalid = 'jessicabrown', 'jessicabrownasdf'
        when 'bandcamp'
          valid, invalid = 'hucci', 'huccixxxxxx'
        when 'bandcamp-fan'
          valid, invalid = 'iguanaden', 'iguanadenxxxxxx'
        when 'fandalism'
          valid, invalid = 'pud', 'pudxxxx'
        when 'rec_youtube'
          valid, invalid = 'https://www.youtube.com/watch?v=i_xFOmYxKYw', 'https://www.zzzyoutube.com'
          rec_id = 'i_xFOmYxKYw'
        when 'rec_soundcloud'
          valid, invalid = 'https://soundcloud.com/zedsdead/winter-mix', 'https://soundcloud.com/zedsdead/winter-mixxx'
          rec_id = '187320651'
        else
          valid, invalid = '', ''
        end
        next if valid.blank?
        2.times do |nn|
          get :validate_data, sitetype:sitetype, data: 0==nn ? valid : invalid
          response.should be_success
          json = JSON.parse(response.body)

          if Utils.recording_source?(sitetype)
            expect(json['message']).to eq(0==nn ? 'Valid Site' : 'Invalid Site')
            expect(json['recording_id']).to eq(0==nn ? rec_id : nil)
          else
            expect(json['message']).to eq(0==nn ? 'Valid Site' : 'Invalid Site')
          end
        end
      end
    end

  end

  describe "audio_latency" do
    it "updates both connection and user" do

      post :audio_latency, id: user.id, client_id: conn.client_id, audio_latency: 3.5, :format => 'json'
      response.should be_success

      conn.reload
      conn.last_jam_audio_latency.should == 3.5

      user.reload
      conn.user.last_jam_audio_latency.should == 3.5
    end

    it "if connection does not exist, user is still updated" do

      post :audio_latency, id: user.id, client_id: 'nothingness', audio_latency: 3.5, :format => 'json'
      response.should be_success

      user.reload
      conn.user.last_jam_audio_latency.should == 3.5
    end

    it "ignores latencies of 2 or less" do
      post :audio_latency, id: user.id, client_id: conn.client_id, audio_latency: 2, :format => 'json'
      response.should be_success

      conn.reload
      conn.last_jam_audio_latency.should == 5

      user.reload
      conn.user.last_jam_audio_latency.should == 5
    end
  end
end
