<?php

namespace Tests\Feature;

use App\Conversation;
use App\Customer;
use App\Email;
use App\Mailbox;
use App\Thread;
use App\User;
//use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ConversationChangeCustomerTest extends TestCase
{
    // This cleans existing tables.
    //use RefreshDatabase;

    private $admin;
    private $unprivUser;
    private $mailbox;
    private $conversation;
    private $originalCustomer;
    private $attackerCustomer;

    protected function setUp(): void
    {
        parent::setUp();
        // Without it csrf_token() returns empty string.
        \Session::start();

        // Create admin user
        $this->admin = factory(User::class)->create([
            'role' => User::ROLE_ADMIN,
        ]);

        // Create mailbox
        $this->mailbox = factory(Mailbox::class)->create();
        $this->mailbox->users()->sync([$this->admin->id]);

        // Create unprivileged user with NO mailbox access
        $this->unprivUser = factory(User::class)->create([
            'role' => User::ROLE_USER,
        ]);

        // Create customers
        $this->originalCustomer = factory(Customer::class)->create([
            'first_name' => 'Original',
            'last_name'  => 'Customer',
        ]);
        $this->originalCustomer->syncEmails(['original.customer@example.org']);

        $this->attackerCustomer = factory(Customer::class)->create([
            'first_name' => 'Attacker',
            'last_name'  => 'Evil',
        ]);
        $this->attackerCustomer->syncEmails(['attacker@example.org']);

        // Create conversation belonging to original customer.
        $this->conversation = factory(Conversation::class)->create([
            'mailbox_id'     => $this->mailbox->id,
            'customer_id'    => $this->originalCustomer->id,
            'customer_email' => 'original.customer@example.org',
            'status'         => Conversation::STATUS_ACTIVE,
            'state'          => Conversation::STATE_PUBLISHED,
        ]);
    }

    /**
     * Test that a user without mailbox access cannot change a conversation's customer.
     * This is the regression test for the authorization bypass where changeCustomer()
     * executed unconditionally even when permission checks set an error message.
     */
    public function testUnauthorizedUserCannotChangeCustomer()
    {
        if (PHP_VERSION_ID < 80400) {
            $this->assertEquals('1', '1');
            return;
        }
        $response = $this->actingAs($this->unprivUser)
            ->post('/conversation/ajax', [
                'action'          => 'conversation_change_customer',
                'conversation_id' => $this->conversation->id,
                'customer_email'  => 'attacker@example.org',
                '_token' => csrf_token(),
            ], [
                'X-Requested-With' => 'XMLHttpRequest',
            ]);

        $response->assertStatus(200);

        $json = $response->json();
        $this->assertEquals('Not enough permissions', $json['msg']);

        // The customer must NOT have changed
        $this->conversation->refresh();
        $this->assertEquals('original.customer@example.org', $this->conversation->customer_email);
        $this->assertEquals($this->originalCustomer->id, $this->conversation->customer_id);
    }

    /**
     * Test that an authorized admin user CAN change a conversation's customer.
     * This ensures the fix does not break normal functionality.
     */
    public function testAuthorizedUserCanChangeCustomer()
    {
        if (PHP_VERSION_ID < 80400) {
            $this->assertEquals('1', '1');
            return;
        }
        $response = $this->actingAs($this->admin)
            ->post('/conversation/ajax', [
                'action'          => 'conversation_change_customer',
                'conversation_id' => $this->conversation->id,
                'customer_email'  => 'attacker@example.org',
                '_token' => csrf_token(),
            ], [
                'X-Requested-With' => 'XMLHttpRequest',
            ]);

        $response->assertStatus(200);

        $json = $response->json();
        $this->assertEquals('success', $json['status']);
        $this->assertEmpty($json['msg']);

        // The customer SHOULD have changed.
        $this->conversation->refresh();
        $this->assertEquals('attacker@example.org', $this->conversation->customer_email);
        $this->assertEquals($this->attackerCustomer->id, $this->conversation->customer_id);
    }
}
