<?php

namespace Tests\Feature\Modules\Segments\ControllersLogic;

use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Models\Segment;
use App\Models\SegmentConstant;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use PHPUnit\Framework\Attributes\Group;
use Spatie\Permission\Models\Permission;
use Tests\TestCase;

#[Group('feature')]
#[Group('segments')]
#[Group('logic')]
#[Group('ok_to_run')]
class UpdateConstantLogic2Test extends TestCase
{
    /** @var User */
    private $admin;

    /** @var Segment */
    private $segment;

    protected function setUp(): void
    {
        parent::setUp();

        // A R R A N G E
        // Create an admin user for authentication
        $email = 'admin_update_constant_execution@example.com';
        $this->admin = User::where('email', $email)->first();
        if (!$this->admin) {
            $this->admin = new User();
            $this->admin->email = $email;
            $this->admin->name = 'Admin Update Constant Execution';
            $this->admin->password = Hash::make('password');
            $this->admin->type = RoleTypes::ADMIN;
            $this->admin->status = 1;
            $this->admin->save();
        }

        // Ensure user has necessary permissions
        $permission = Permission::firstOrCreate(['name' => 'edit segment_constant', 'guard_name' => 'api']);
        $this->admin->givePermissionTo($permission);
        $permission = Permission::firstOrCreate(['name' => 'add segment_constant', 'guard_name' => 'api']);
        $this->admin->givePermissionTo($permission);

        // Create a test segment
        $this->segment = new Segment();
        $this->segment->name = 'Update Constant Execution Segment';
        $this->segment->save();
    }

    /**
     * Test updating an existing segment constant without Mockery.
     *
     * @return void
     */
    public function test_it_can_update_existing_constant()
    {
        // A R R A N G E
        $reference = 'execution_test_ref';
        $detail = ['foo' => 'bar'];

        $constant = new SegmentConstant();
        $constant->segment_id = $this->segment->id;
        $constant->name = 'Old Name';
        $constant->reference = $reference;
        $constant->detail = (object) ['old' => 'data'];
        $constant->save();

        $payload = [
            'name' => 'Updated Name',
            'reference' => $reference,
            'detail' => $detail
        ];

        // A C T
        $response = $this->actingAs($this->admin, 'api')
            ->putJson("/api/v1/segment/{$this->segment->id}/constant/update", $payload);

        // A S S E R T
        $response->assertStatus(200);
        $response->assertJsonPath('payload.data.name', 'Updated Name');
        $response->assertJsonPath('payload.data.reference', $reference);

        $this->assertDatabaseHas('segment_constants', [
            'segment_id' => $this->segment->id,
            'reference' => $reference,
            'name' => 'Updated Name'
        ]);

        $updatedConstant = SegmentConstant::where('reference', $reference)->first();
        $this->assertEquals((object) $detail, $updatedConstant->detail);
    }

    /**
     * Test creating a constant if it doesn't exist during update.
     *
     * @return void
     */
    public function test_it_creates_constant_if_not_exists()
    {
        // A R R A N G E
        $reference = 'new_execution_test_ref';
        $detail = ['new' => 'data'];

        $payload = [
            'name' => 'New Constant',
            'reference' => $reference,
            'detail' => $detail
        ];

        // A C T
        $response = $this->actingAs($this->admin, 'api')
            ->putJson("/api/v1/segment/{$this->segment->id}/constant/update", $payload);

        // A S S E R T
        $response->assertStatus(200);

        $this->assertDatabaseHas('segment_constants', [
            'segment_id' => $this->segment->id,
            'reference' => $reference,
            'name' => 'New Constant'
        ]);
    }
}
