require 'spec_helper'

describe "Band API", :type => :api do

  include Rack::Test::Methods

  subject { page }

  describe "profile" do
    let(:band) { FactoryGirl.create(:band) }
    let(:user) { FactoryGirl.create(:user) }
    let(:fan) { FactoryGirl.create(:fan) }

    def login(email, password, http_code, success)
      # login as fan
      post '/api/auth_session.json', { :email => email, :password => password }.to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should == http_code
      JSON.parse(last_response.body).should == { "success" => success }
    end

    ################################## BANDS ##################################
    def create_band(authenticated_user, name, website, biography, city, state, country, genres, photo_url, logo_url)
      post "/api/bands.json", { :name => name,
                                :website => website,
                                :biography => biography,
                                :city => city,
                                :state => state,
                                :country => country,
                                :genres => genres,
                                :photo_url => photo_url,
                                :logo_url => logo_url
                              }.to_json, 
                              "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def update_band(authenticated_user, band_id, name, website, biography, city, state, country, genres, photo_url, logo_url)
      post "/api/bands/#{band_id}.json", { :name => name,
                                           :website => website,
                                           :biography => biography,
                                           :city => city,
                                           :state => state,
                                           :country => country,
                                           :genres => genres,
                                           :photo_url => photo_url,
                                           :logo_url => logo_url
                                         }.to_json, 
                                         "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_band(authenticated_user, band_id)
      get "/api/bands/#{band_id}.json", "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    ########################## RECORDINGS #########################
    def create_band_recording(authenticated_user, band_id, description, public, genres)
      post "/api/bands/#{band_id}/recordings.json", { :description => description, :public => public, :genres => genres }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def update_band_recording()
    end

    def get_band_recordings()
    end

    def get_band_recording()
    end

    def delete_band_recording()
    end

    ########################## INVITATIONS #########################
    def create_band_invitation(band_id, user_id)
      post "/api/bands/#{band_id}/invitations.json", { :band_id => band_id, :user_id => user_id }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_band_invitations(band_id)
      get "/api/bands/#{band_id}/invitations.json", "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_band_invitation(band_id, invitation_id)
      get "/api/bands/#{band_id}/invitations/#{invitation_id}.json", "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def delete_band_invitation(band_id, invitation_id)
      delete "/api/bands/#{band_id}/invitations/#{invitation_id}.json", "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    context "when logged in as musician" do
      before(:each) do
        login(user.email, user.password, 200, true)
      end

      it "should allow band creation" do

        last_response = create_band(user, "My Band", "http://www.myband.com", "Bio", "Apex", "NC", "USA", ["country"], "www.photos.com", "www.logos.com")
        last_response.status.should == 201

        new_band = JSON.parse(last_response.body)
        new_band["name"].should == "My Band"

        last_response = get_band(user, new_band["id"])
        last_response.status.should == 200

        # ensure creator is member of band after band creation
        band_details = JSON.parse(last_response.body)
        band_details["id"].should == new_band["id"]
        band_details["musicians"][0]["id"].should == user.id
        band_details["genres"].size.should == 1
      end

      it "should prevent bands with less than 1 genre" do
        last_response = create_band(user, "My Band", "http://www.myband.com", "Bio", "Apex", "NC", "USA", nil, "www.photos.com", "www.logos.com")
        last_response.status.should == 400
        error_msg = JSON.parse(last_response.body)
        error_msg["message"].should == ValidationMessages::GENRE_MINIMUM_NOT_MET
      end

      it "should prevent bands with more than 1 genre" do
        last_response = create_band(user, "My Band", "http://www.myband.com", "Bio", "Apex", "NC", "USA", ["african", "country"], "www.photos.com", "www.logos.com")
        last_response.status.should == 400
        error_msg = JSON.parse(last_response.body)
        error_msg["message"].should == ValidationMessages::GENRE_LIMIT_EXCEEDED
      end
    end   

    context "when logged in as musician who is in Band A" do

      before(:each) do
        login(user.email, user.password, 200, true)
        band.genres << Genre.find("hip hop")
        #band.genres << Genre.find("african")
        #band.genres << Genre.find("country")
        user.bands << band
      end

      it "should allow user to update attributes of band A" do
        
        band.genres.size.should == 1

        last_response = update_band(user, band.id, "Brian's Band", "http://www.briansband.com", "Bio", "Apex", "NC", "USA", ["african"], "www.photos.com", "www.logos.com")
        last_response.status.should == 200

        updated_band = JSON.parse(last_response.body)

        # spot check fields in response entity
        updated_band["name"].should == "Brian's Band"
        updated_band["website"].should == "http://www.briansband.com"
        updated_band["genres"].size.should == 1
        
        # retrieve the band to get details
        last_response = get_band(user, band.id)
        last_response.status.should == 200
        band_details = JSON.parse(last_response.body)
        band_details["name"].should == "Brian's Band"
        band_details["website"].should == "http://www.briansband.com"
        band_details["biography"].should == "Bio"
        band_details["genres"].size.should == 1
      end

      it "should allow user to create recording for band A" do
      end

      it "should allow user to update recording of band A" do
      end

      it "should allow user to delete recording of Band A" do
      end

      it "should allow user to view public recording of Band A" do
      end

      it "should allow user to view private recording of Band A" do
      end

      it "should allow user to create invitation to a Musician for band A" do

        # TEST 1 - CREATE INVITATION
        recipient = FactoryGirl.create(:user)
        last_response = create_band_invitation(band.id, recipient.id)
        last_response.status.should == 201

        invitation = JSON.parse(last_response.body)

        # test response entity
        invitation["accepted"].nil?.should == true
        invitation["sender"]["id"].should == user.id
        invitation["recipient"]["id"].should == recipient.id
        invitation["band"]["id"].should == band.id

        # test receiver relationships
        recipient.received_band_invitations.size.should == 1
        recipient.sent_band_invitations.size.should == 0

        # test sender relationships
        user.received_band_invitations.size.should == 0
        user.sent_band_invitations.size.should == 1

        # test band relationship
        band.invitations.size.should == 1

        # TEST 2 - RETRIEVE INVITATION LIST
        last_response = get_band_invitations(band.id)
        last_response.status.should == 200
        invitations = JSON.parse(last_response.body)
        invitations.size.should == 1
        invitations[0]["id"].should == invitation["id"]
        invitations[0]["accepted"].nil?.should == true
        invitations[0]["sender"]["id"].should == user.id
        invitations[0]["recipient"]["id"].should == recipient.id
        invitations[0]["band"]["id"].should == band.id

        # TEST 3 - RETRIEVE INVITATION DETAILS
        last_response = get_band_invitation(band.id, invitation["id"])
        last_response.status.should == 200
        invitation_details = JSON.parse(last_response.body)
        invitation_details["accepted"].nil?.should == true
        invitation_details["sender"]["id"].should == user.id
        invitation_details["recipient"]["id"].should == recipient.id
        invitation_details["band"]["id"].should == band.id

        # TEST 4 -DELETE INVITATION
        last_response = delete_band_invitation(band.id, invitation["id"])
        last_response.status.should == 204

        # test receiver relationships
        recipient.received_band_invitations.size.should == 0
        recipient.sent_band_invitations.size.should == 0

        # test sender relationships
        user.received_band_invitations.size.should == 0
        user.sent_band_invitations.size.should == 0

        # test band relationship
        band.invitations.size.should == 0
      end

      it "should not allow user to create invitation to a Fan for band A" do
        recipient = FactoryGirl.create(:fan)
        last_response = create_band_invitation(band.id, recipient.id)
        last_response.status.should == 400
        error_msg = JSON.parse(last_response.body)
        error_msg["message"].should == BandInvitation::BAND_INVITATION_FAN_RECIPIENT_ERROR

        # test receiver relationships
        recipient.received_band_invitations.size.should == 0
        recipient.sent_band_invitations.size.should == 0

        # test sender relationships
        user.received_band_invitations.size.should == 0
        user.sent_band_invitations.size.should == 0

        # test band relationship
        band.invitations.size.should == 0
      end

      it "should raise exception when attempting to retrieve a non-existent invitation" do
        # retrieve non-existent invitation
        last_response = get_band_invitation(band.id, "2")
        last_response.status.should == 404
        error_msg = JSON.parse(last_response.body)
        error_msg["message"].should == ValidationMessages::BAND_INVITATION_NOT_FOUND
      end

      it "should raise exception when attempting to delete a non-existent invitation" do
        # delete non-existent invitation
        last_response = delete_band_invitation(band.id, "2")
        last_response.status.should == 404
        error_msg = JSON.parse(last_response.body)
        error_msg["message"].should == ValidationMessages::BAND_INVITATION_NOT_FOUND
      end
    end

    context "when logged in as user who is not in band A" do
      before(:each) do
        login(user.email, user.password, 200, true)
        band.genres << Genre.find("hip hop")
        #band.genres << Genre.find("african")
        #band.genres << Genre.find("country")
      end

      it "should not allow user to update attributes of band A" do
      end

      it "should not allow user to create invitation for band A" do
      end

      it "should not allow user to create recording for band A" do
      end

      it "should not allow user to update recording of band A" do
      end

      it "should not allow user to delete recording of Band A" do
      end

      it "should allow user to view public recording of Band A" do
      end

      it "should not allow user to view private recording of Band A" do
      end

      it "should not allow user to see invitation list of band A" do
      end
    end

    context "when logged in as fan" do
      it "should not allow band creation" do
      end

      it "should not allow band invitation creation" do
      end
    end
  end
end