require 'rails_helper'

RSpec.describe Captain::FollowUpService do
  let(:account) { create(:account) }
  let(:inbox) { create(:inbox, account: account) }
  let(:conversation) { create(:conversation, account: account, inbox: inbox) }
  let(:user_message) { 'Make it more concise' }
  let(:follow_up_context) do
    {
      'event_name' => 'professional',
      'original_context' => 'Please help me with this issue',
      'last_response' => 'I would be happy to assist you with this matter.',
      'conversation_history' => [
        { 'role' => 'user', 'content' => 'Make it shorter' },
        { 'role' => 'assistant', 'content' => 'Happy to help with this.' }
      ]
    }
  end
  let(:service) do
    described_class.new(
      account: account,
      follow_up_context: follow_up_context,
      user_message: user_message,
      conversation_display_id: conversation.display_id
    )
  end

  before do
    # Stub captain enabled check to allow specs to test base functionality
    # without enterprise module interference
    allow(account).to receive(:feature_enabled?).and_call_original
    allow(account).to receive(:feature_enabled?).with('captain_tasks').and_return(true)
  end

  describe '#perform' do
    context 'when conversation_display_id is provided' do
      it 'resolves conversation for instrumentation' do
        expect(service.send(:conversation)).to eq(conversation)
      end
    end

    context 'when follow-up context exists' do
      it 'constructs messages array with full conversation history' do
        expect(service).to receive(:make_api_call) do |args|
          expect(args[:feature]).to eq('editor')
          messages = args[:messages]

          expect(messages).to match(
            [
              a_hash_including(role: 'system', content: include('tone rewrite (professional)')),
              { role: 'user', content: 'Please help me with this issue' },
              { role: 'assistant', content: 'I would be happy to assist you with this matter.' },
              { role: 'user', content: 'Make it shorter' },
              { role: 'assistant', content: 'Happy to help with this.' },
              { role: 'user', content: 'Make it more concise' }
            ]
          )

          { message: 'Refined response' }
        end

        service.perform
      end

      it 'returns updated follow-up context' do
        allow(service).to receive(:make_api_call).and_return({ message: 'Refined response' })

        result = service.perform

        expect(result[:message]).to eq('Refined response')
        expect(result[:follow_up_context]['last_response']).to eq('Refined response')
        expect(result[:follow_up_context]['conversation_history'].length).to eq(4)
        expect(result[:follow_up_context]['conversation_history'][-2]['content']).to eq('Make it more concise')
        expect(result[:follow_up_context]['conversation_history'][-1]['content']).to eq('Refined response')
      end
    end

    context 'when follow-up context is missing' do
      let(:follow_up_context) { nil }

      it 'returns error with 400 code' do
        result = service.perform

        expect(result[:error]).to eq('Follow-up context missing')
        expect(result[:error_code]).to eq(400)
      end
    end
  end

  describe '#build_follow_up_system_prompt' do
    it 'describes tone rewrite actions' do
      %w[professional casual friendly confident straightforward].each do |tone|
        session = { 'event_name' => tone }
        prompt = service.send(:build_follow_up_system_prompt, session)

        expect(prompt).to include("tone rewrite (#{tone})")
        expect(prompt).to include('help them refine the result')
      end
    end

    it 'describes fix_spelling_grammar action' do
      session = { 'event_name' => 'fix_spelling_grammar' }
      prompt = service.send(:build_follow_up_system_prompt, session)

      expect(prompt).to include('spelling and grammar correction')
    end

    it 'describes improve action' do
      session = { 'event_name' => 'improve' }
      prompt = service.send(:build_follow_up_system_prompt, session)

      expect(prompt).to include('message improvement')
    end

    it 'describes summarize action' do
      session = { 'event_name' => 'summarize' }
      prompt = service.send(:build_follow_up_system_prompt, session)

      expect(prompt).to include('conversation summary')
    end

    it 'describes reply_suggestion action' do
      session = { 'event_name' => 'reply_suggestion' }
      prompt = service.send(:build_follow_up_system_prompt, session)

      expect(prompt).to include('reply suggestion')
    end

    it 'describes label_suggestion action' do
      session = { 'event_name' => 'label_suggestion' }
      prompt = service.send(:build_follow_up_system_prompt, session)

      expect(prompt).to include('label suggestion')
    end

    it 'uses event_name directly for unknown actions' do
      session = { 'event_name' => 'custom_action' }
      prompt = service.send(:build_follow_up_system_prompt, session)

      expect(prompt).to include('custom_action')
    end
  end

  describe '#describe_previous_action' do
    it 'returns tone description for tone operations' do
      expect(service.send(:describe_previous_action, 'professional')).to eq('tone rewrite (professional)')
      expect(service.send(:describe_previous_action, 'casual')).to eq('tone rewrite (casual)')
      expect(service.send(:describe_previous_action, 'friendly')).to eq('tone rewrite (friendly)')
      expect(service.send(:describe_previous_action, 'confident')).to eq('tone rewrite (confident)')
      expect(service.send(:describe_previous_action, 'straightforward')).to eq('tone rewrite (straightforward)')
    end

    it 'returns specific descriptions for other operations' do
      expect(service.send(:describe_previous_action, 'fix_spelling_grammar')).to eq('spelling and grammar correction')
      expect(service.send(:describe_previous_action, 'improve')).to eq('message improvement')
      expect(service.send(:describe_previous_action, 'summarize')).to eq('conversation summary')
      expect(service.send(:describe_previous_action, 'reply_suggestion')).to eq('reply suggestion')
      expect(service.send(:describe_previous_action, 'label_suggestion')).to eq('label suggestion')
    end

    it 'returns event name for unknown operations' do
      expect(service.send(:describe_previous_action, 'unknown')).to eq('unknown')
    end
  end
end
