require 'rails_helper'

RSpec.describe 'Api::V1::PhantomPlayers', type: :request do
  let(:user) { create(:user) }
  let(:access_token) do
    Doorkeeper::AccessToken.create!(resource_owner_id: user.id, expires_in: 30.days, scopes: 'public')
  end
  let(:auth_headers) { { 'Authorization' => "Bearer #{access_token.token}" } }

  let(:crew) { create(:crew) }
  let!(:captain_membership) { create(:crew_membership, crew: crew, user: user, role: :captain) }

  describe 'GET /api/v1/crews/:crew_id/phantom_players' do
    let!(:phantom1) { create(:phantom_player, crew: crew, name: 'Phantom A') }
    let!(:phantom2) { create(:phantom_player, crew: crew, name: 'Phantom B') }

    context 'as crew member' do
      it 'returns all phantom players' do
        get "/api/v1/crews/#{crew.id}/phantom_players", headers: auth_headers

        expect(response).to have_http_status(:ok)
        json = JSON.parse(response.body)
        expect(json['phantom_players'].length).to eq(2)
      end
    end

    context 'as non-member' do
      let(:other_user) { create(:user) }
      let(:other_token) do
        Doorkeeper::AccessToken.create!(resource_owner_id: other_user.id, expires_in: 30.days, scopes: 'public')
      end
      let(:other_headers) { { 'Authorization' => "Bearer #{other_token.token}" } }

      it 'returns unauthorized' do
        get "/api/v1/crews/#{crew.id}/phantom_players", headers: other_headers
        expect(response).to have_http_status(:unauthorized)
      end
    end
  end

  describe 'GET /api/v1/crews/:crew_id/phantom_players/:id' do
    let!(:phantom) { create(:phantom_player, crew: crew) }

    it 'returns the phantom player with scores' do
      get "/api/v1/crews/#{crew.id}/phantom_players/#{phantom.id}", headers: auth_headers

      expect(response).to have_http_status(:ok)
      json = JSON.parse(response.body)
      expect(json['phantom_player']['name']).to eq(phantom.name)
      expect(json['phantom_player']).to have_key('total_score')
    end
  end

  describe 'POST /api/v1/crews/:crew_id/phantom_players' do
    let(:valid_params) do
      {
        phantom_player: {
          name: 'New Phantom',
          granblue_id: '12345678',
          notes: 'Former member'
        }
      }
    end

    context 'as officer' do
      it 'creates a phantom player' do
        expect {
          post "/api/v1/crews/#{crew.id}/phantom_players",
               params: valid_params,
               headers: auth_headers
        }.to change(PhantomPlayer, :count).by(1)

        expect(response).to have_http_status(:created)
        json = JSON.parse(response.body)
        expect(json['phantom_player']['name']).to eq('New Phantom')
        expect(json['phantom_player']['granblue_id']).to eq('12345678')
      end

      it 'returns validation error for missing name' do
        post "/api/v1/crews/#{crew.id}/phantom_players",
             params: { phantom_player: { name: '' } },
             headers: auth_headers

        expect(response).to have_http_status(:unprocessable_entity)
      end
    end

    context 'as regular member' do
      let!(:captain_membership) { create(:crew_membership, crew: crew, user: user, role: :member) }

      it 'returns unauthorized' do
        post "/api/v1/crews/#{crew.id}/phantom_players",
             params: valid_params,
             headers: auth_headers

        expect(response).to have_http_status(:unauthorized)
      end
    end
  end

  describe 'PUT /api/v1/crews/:crew_id/phantom_players/:id' do
    let!(:phantom) { create(:phantom_player, crew: crew, name: 'Old Name') }

    context 'as officer' do
      it 'updates the phantom player' do
        put "/api/v1/crews/#{crew.id}/phantom_players/#{phantom.id}",
            params: { phantom_player: { name: 'New Name' } },
            headers: auth_headers

        expect(response).to have_http_status(:ok)
        json = JSON.parse(response.body)
        expect(json['phantom_player']['name']).to eq('New Name')
      end
    end

    context 'as regular member' do
      let!(:captain_membership) { create(:crew_membership, crew: crew, user: user, role: :member) }

      it 'returns unauthorized' do
        put "/api/v1/crews/#{crew.id}/phantom_players/#{phantom.id}",
            params: { phantom_player: { name: 'New Name' } },
            headers: auth_headers

        expect(response).to have_http_status(:unauthorized)
      end
    end
  end

  describe 'DELETE /api/v1/crews/:crew_id/phantom_players/:id' do
    let!(:phantom) { create(:phantom_player, crew: crew) }

    context 'as officer' do
      it 'deletes the phantom player' do
        expect {
          delete "/api/v1/crews/#{crew.id}/phantom_players/#{phantom.id}",
                 headers: auth_headers
        }.to change(PhantomPlayer, :count).by(-1)

        expect(response).to have_http_status(:no_content)
      end
    end

    context 'as regular member' do
      let!(:captain_membership) { create(:crew_membership, crew: crew, user: user, role: :member) }

      it 'returns unauthorized' do
        delete "/api/v1/crews/#{crew.id}/phantom_players/#{phantom.id}",
               headers: auth_headers

        expect(response).to have_http_status(:unauthorized)
      end
    end
  end

  describe 'POST /api/v1/crews/:crew_id/phantom_players/:id/assign' do
    let!(:phantom) { create(:phantom_player, crew: crew) }
    let(:target_user) { create(:user) }
    let!(:target_membership) { create(:crew_membership, crew: crew, user: target_user, role: :member) }

    context 'as officer' do
      it 'assigns the phantom to a user' do
        post "/api/v1/crews/#{crew.id}/phantom_players/#{phantom.id}/assign",
             params: { user_id: target_user.id },
             headers: auth_headers

        expect(response).to have_http_status(:ok)
        json = JSON.parse(response.body)
        expect(json['phantom_player']['claimed']).to be true
        expect(json['phantom_player']['claimed_by']['id']).to eq(target_user.id)
      end

      it 'returns error for non-crew member' do
        non_member = create(:user)
        post "/api/v1/crews/#{crew.id}/phantom_players/#{phantom.id}/assign",
             params: { user_id: non_member.id },
             headers: auth_headers

        expect(response).to have_http_status(:not_found)
      end
    end

    context 'as regular member' do
      let!(:captain_membership) { create(:crew_membership, crew: crew, user: user, role: :member) }

      it 'returns unauthorized' do
        post "/api/v1/crews/#{crew.id}/phantom_players/#{phantom.id}/assign",
             params: { user_id: target_user.id },
             headers: auth_headers

        expect(response).to have_http_status(:unauthorized)
      end
    end
  end

  describe 'POST /api/v1/crews/:crew_id/phantom_players/:id/confirm_claim' do
    let(:claimer) { create(:user) }
    let!(:claimer_membership) { create(:crew_membership, crew: crew, user: claimer, role: :member) }
    let!(:phantom) { create(:phantom_player, crew: crew, claimed_by: claimer) }

    let(:claimer_token) do
      Doorkeeper::AccessToken.create!(resource_owner_id: claimer.id, expires_in: 30.days, scopes: 'public')
    end
    let(:claimer_headers) { { 'Authorization' => "Bearer #{claimer_token.token}" } }

    it 'confirms the claim' do
      post "/api/v1/crews/#{crew.id}/phantom_players/#{phantom.id}/confirm_claim",
           headers: claimer_headers

      expect(response).to have_http_status(:ok)
      json = JSON.parse(response.body)
      expect(json['phantom_player']['claim_confirmed']).to be true
    end

    it 'returns error for wrong user' do
      post "/api/v1/crews/#{crew.id}/phantom_players/#{phantom.id}/confirm_claim",
           headers: auth_headers

      expect(response).to have_http_status(:forbidden)
      json = JSON.parse(response.body)
      expect(json['code']).to eq('not_claimed_by_user')
    end
  end
end
