<?php

namespace Tests\Unit\Actions;

use App\Actions\CreatePlatformAccountAction;
use App\Enums\AccountStatusEnum;
use App\Enums\PlatformEnum;
use App\Exceptions\PlatformAuthException;
use App\Models\PlatformAccount;
use App\Models\PlatformInstance;
use App\Services\Auth\LemmyAuthService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Mockery;
use Mockery\MockInterface;
use Tests\TestCase;

class CreatePlatformAccountActionTest extends TestCase
{
    use RefreshDatabase;

    private CreatePlatformAccountAction $action;

    /** @var LemmyAuthService&MockInterface */
    private LemmyAuthService $lemmyAuthService;

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

        $this->lemmyAuthService = Mockery::mock(LemmyAuthService::class);
        $this->action = new CreatePlatformAccountAction($this->lemmyAuthService);
    }

    public function test_creates_platform_account_with_new_instance(): void
    {
        $this->lemmyAuthService
            ->shouldReceive('authenticate')
            ->once()
            ->with('https://lemmy.world', 'testuser', 'testpass')
            ->andReturn([
                'jwt' => 'test-jwt-token',
                'person_view' => [
                    'person' => [
                        'id' => 42,
                        'display_name' => 'Test User',
                        'bio' => 'A test bio',
                    ],
                ],
            ]);

        $account = $this->action->execute('lemmy.world', 'testuser', 'testpass');

        $this->assertInstanceOf(PlatformAccount::class, $account);
        $this->assertEquals('testuser', $account->username);
        $this->assertEquals('https://lemmy.world', $account->instance_url);
        $this->assertEquals('lemmy', $account->platform->value);
        $this->assertTrue($account->is_active);
        $this->assertSame(AccountStatusEnum::HEALTHY, $account->status);
        $this->assertEquals(42, $account->settings['person_id']);
        $this->assertEquals('Test User', $account->settings['display_name']);
        $this->assertEquals('A test bio', $account->settings['description']);
        $this->assertEquals('test-jwt-token', $account->settings['api_token']);
        $this->assertDatabaseHas('platform_instances', [
            'url' => 'https://lemmy.world',
            'platform' => 'lemmy',
        ]);
    }

    public function test_reuses_existing_platform_instance(): void
    {
        $existingInstance = PlatformInstance::factory()->create([
            'url' => 'https://lemmy.world',
            'platform' => 'lemmy',
            'name' => 'Existing Name',
        ]);

        $this->lemmyAuthService
            ->shouldReceive('authenticate')
            ->once()
            ->andReturn([
                'jwt' => 'token',
                'person_view' => ['person' => ['id' => 1, 'display_name' => null, 'bio' => null]],
            ]);

        $account = $this->action->execute('lemmy.world', 'user', 'pass');

        $this->assertEquals($existingInstance->id, $account->settings['platform_instance_id']);
        $this->assertEquals(1, PlatformInstance::where('url', 'https://lemmy.world')->count());
    }

    public function test_propagates_auth_exception(): void
    {
        $this->lemmyAuthService
            ->shouldReceive('authenticate')
            ->once()
            ->andThrow(new PlatformAuthException(PlatformEnum::LEMMY, 'Invalid credentials'));

        try {
            $this->action->execute('lemmy.world', 'baduser', 'badpass');
            $this->fail('Expected PlatformAuthException was not thrown');
        } catch (PlatformAuthException) {
            // No instance or account should be created on auth failure
            $this->assertDatabaseCount('platform_instances', 0);
            $this->assertDatabaseCount('platform_accounts', 0);
        }
    }
}
