require 'rails_helper'

RSpec.describe 'Crews API', type: :request do
  let(:user) { create(:user) }
  let(:other_user) { create(:user) }
  let(:access_token) do
    Doorkeeper::AccessToken.create!(resource_owner_id: user.id, expires_in: 30.days, scopes: 'public')
  end
  let(:other_access_token) do
    Doorkeeper::AccessToken.create!(resource_owner_id: other_user.id, expires_in: 30.days, scopes: 'public')
  end
  let(:headers) do
    { 'Authorization' => "Bearer #{access_token.token}", 'Content-Type' => 'application/json' }
  end
  let(:other_headers) do
    { 'Authorization' => "Bearer #{other_access_token.token}", 'Content-Type' => 'application/json' }
  end

  describe 'POST /api/v1/crews' do
    let(:valid_params) do
      {
        crew: {
          name: 'Test Crew',
          gamertag: 'TEST',
          granblue_crew_id: '12345678',
          description: 'A test crew'
        }
      }
    end

    it 'creates a crew and makes user captain' do
      post '/api/v1/crews', params: valid_params.to_json, headers: headers

      expect(response).to have_http_status(:created)
      json = JSON.parse(response.body)
      expect(json['crew']['name']).to eq('Test Crew')
      expect(json['crew']['gamertag']).to eq('TEST')

      user.reload
      expect(user.crew).to be_present
      expect(user.crew_captain?).to be true
    end

    it 'returns error if user already in a crew' do
      crew = create(:crew)
      create(:crew_membership, :captain, crew: crew, user: user)

      post '/api/v1/crews', params: valid_params.to_json, headers: headers

      expect(response).to have_http_status(:unprocessable_entity)
      json = JSON.parse(response.body)
      expect(json['message']).to eq('You are already in a crew')
    end

    it 'returns unauthorized without authentication' do
      post '/api/v1/crews', params: valid_params.to_json

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

    it 'validates crew name presence' do
      invalid_params = { crew: { name: '' } }
      post '/api/v1/crews', params: invalid_params.to_json, headers: headers

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

  describe 'GET /api/v1/crew' do
    let(:crew) { create(:crew) }

    before do
      create(:crew_membership, :captain, crew: crew, user: user)
    end

    it 'returns the current user crew' do
      get '/api/v1/crew', headers: headers

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

    it 'returns 404 if user has no crew' do
      user.active_crew_membership.retire!

      get '/api/v1/crew', headers: headers

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

    it 'returns unauthorized without authentication' do
      get '/api/v1/crew'

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

  describe 'PUT /api/v1/crew' do
    let(:crew) { create(:crew) }

    context 'as captain' do
      before do
        create(:crew_membership, :captain, crew: crew, user: user)
      end

      it 'updates the crew' do
        put '/api/v1/crew', params: { crew: { name: 'New Name' } }.to_json, headers: headers

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

    context 'as vice captain' do
      before do
        create(:crew_membership, :captain, crew: crew)
        create(:crew_membership, :vice_captain, crew: crew, user: user)
      end

      it 'updates the crew' do
        put '/api/v1/crew', params: { crew: { name: 'New Name' } }.to_json, headers: headers

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

    context 'as member' do
      before do
        create(:crew_membership, :captain, crew: crew)
        create(:crew_membership, crew: crew, user: user)
      end

      it 'returns unauthorized' do
        put '/api/v1/crew', params: { crew: { name: 'New Name' } }.to_json, headers: headers

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

  describe 'GET /api/v1/crew/members' do
    let(:crew) { create(:crew) }
    let(:captain) { create(:user) }
    let(:member) { create(:user) }

    before do
      create(:crew_membership, :captain, crew: crew, user: captain)
      create(:crew_membership, crew: crew, user: user)
      create(:crew_membership, crew: crew, user: member)
    end

    it 'returns all active members' do
      get '/api/v1/crew/members', headers: headers

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

    it 'does not include retired members' do
      crew.crew_memberships.find_by(user: member).retire!

      get '/api/v1/crew/members', headers: headers

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

  describe 'POST /api/v1/crew/leave' do
    let(:crew) { create(:crew) }

    context 'as regular member' do
      before do
        create(:crew_membership, :captain, crew: crew)
        create(:crew_membership, crew: crew, user: user)
      end

      it 'retires the membership' do
        post '/api/v1/crew/leave', headers: headers

        expect(response).to have_http_status(:no_content)
        user.reload
        expect(user.crew).to be_nil
      end
    end

    context 'as captain' do
      before do
        create(:crew_membership, :captain, crew: crew, user: user)
      end

      it 'returns error' do
        post '/api/v1/crew/leave', headers: headers

        expect(response).to have_http_status(:unprocessable_entity)
        json = JSON.parse(response.body)
        expect(json['message']).to eq('Captain must transfer ownership before leaving')
      end
    end

    context 'when not in crew' do
      it 'returns error' do
        post '/api/v1/crew/leave', headers: headers

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

  describe 'POST /api/v1/crews/:id/transfer_captain' do
    let(:crew) { create(:crew) }
    let(:vice_captain) { create(:user) }

    before do
      create(:crew_membership, :captain, crew: crew, user: user)
      create(:crew_membership, :vice_captain, crew: crew, user: vice_captain)
    end

    it 'transfers captain role to another member' do
      post "/api/v1/crews/#{crew.id}/transfer_captain",
           params: { user_id: vice_captain.id }.to_json,
           headers: headers

      expect(response).to have_http_status(:ok)
      user.reload
      vice_captain.reload
      expect(user.crew_role).to eq('vice_captain')
      expect(vice_captain.crew_role).to eq('captain')
    end

    it 'returns error if target user is not in crew' do
      post "/api/v1/crews/#{crew.id}/transfer_captain",
           params: { user_id: other_user.id }.to_json,
           headers: headers

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

    it 'requires captain role' do
      create(:crew_membership, crew: crew, user: other_user)

      post "/api/v1/crews/#{crew.id}/transfer_captain",
           params: { user_id: vice_captain.id }.to_json,
           headers: other_headers

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