<?php

namespace Tests\Unit\Services\Auth;

use App\Enums\PlatformEnum;
use App\Exceptions\PlatformAuthException;
use App\Models\PlatformAccount;
use App\Services\Auth\LemmyAuthService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;

class LemmyAuthServiceTest extends TestCase
{
    use RefreshDatabase;

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

    public function test_get_token_successfully_authenticates(): void
    {
        // Mock successful HTTP response for both HTTPS and HTTP (fallback)
        Http::fake([
            'https://lemmy.test/api/v3/user/login' => Http::response(['jwt' => 'jwt-123'], 200),
            'http://lemmy.test/api/v3/user/login' => Http::response(['jwt' => 'jwt-123'], 200),
        ]);

        $account = PlatformAccount::factory()->create([
            'username' => 'testuser',
            'password' => 'testpass',
            'instance_url' => 'https://lemmy.test',
        ]);

        $result = app(LemmyAuthService::class)->getToken($account);

        $this->assertEquals('jwt-123', $result);
    }

    public function test_get_token_throws_exception_when_username_missing(): void
    {
        $account = $this->createMock(PlatformAccount::class);
        $account->method('__get')->willReturnCallback(function ($key) {
            return match ($key) {
                'username' => null,
                'password' => 'testpass',
                'instance_url' => 'https://lemmy.test',
                default => null,
            };
        });

        $this->expectException(PlatformAuthException::class);
        $this->expectExceptionMessage('Missing credentials for account: ');

        app(LemmyAuthService::class)->getToken($account);
    }

    public function test_get_token_throws_exception_when_password_missing(): void
    {
        $account = $this->createMock(PlatformAccount::class);
        $account->method('__get')->willReturnCallback(function ($key) {
            return match ($key) {
                'username' => 'testuser',
                'password' => null,
                'instance_url' => 'https://lemmy.test',
                default => null,
            };
        });

        $this->expectException(PlatformAuthException::class);
        $this->expectExceptionMessage('Missing credentials for account: testuser');

        app(LemmyAuthService::class)->getToken($account);
    }

    public function test_get_token_throws_exception_when_instance_url_missing(): void
    {
        $account = $this->createMock(PlatformAccount::class);
        $account->method('__get')->willReturnCallback(function ($key) {
            return match ($key) {
                'username' => 'testuser',
                'password' => 'testpass',
                'instance_url' => null,
                default => null,
            };
        });

        $this->expectException(PlatformAuthException::class);
        $this->expectExceptionMessage('Missing credentials for account: testuser');

        app(LemmyAuthService::class)->getToken($account);
    }

    public function test_get_token_throws_exception_when_login_fails(): void
    {
        // Mock failed HTTP response for both HTTPS and HTTP
        Http::fake([
            'https://lemmy.test/api/v3/user/login' => Http::response(['error' => 'Invalid credentials'], 401),
            'http://lemmy.test/api/v3/user/login' => Http::response(['error' => 'Invalid credentials'], 401),
        ]);

        $account = $this->createMock(PlatformAccount::class);
        $account->method('__get')->willReturnCallback(function ($key) {
            return match ($key) {
                'username' => 'failingUser',
                'password' => 'badpass',
                'instance_url' => 'https://lemmy.test',
                default => null,
            };
        });

        $this->expectException(PlatformAuthException::class);
        $this->expectExceptionMessage('Login failed for account: failingUser');

        app(LemmyAuthService::class)->getToken($account);
    }

    public function test_get_token_throws_exception_when_login_returns_false(): void
    {
        // Mock response with empty/missing JWT for both HTTPS and HTTP
        Http::fake([
            'https://lemmy.test/api/v3/user/login' => Http::response(['success' => false], 200),
            'http://lemmy.test/api/v3/user/login' => Http::response(['success' => false], 200),
        ]);

        $account = $this->createMock(PlatformAccount::class);
        $account->method('__get')->willReturnCallback(function ($key) {
            return match ($key) {
                'username' => 'emptyUser',
                'password' => 'pass',
                'instance_url' => 'https://lemmy.test',
                default => null,
            };
        });

        $this->expectException(PlatformAuthException::class);
        $this->expectExceptionMessage('Login failed for account: emptyUser');

        app(LemmyAuthService::class)->getToken($account);
    }

    public function test_platform_auth_exception_contains_correct_platform(): void
    {
        $account = $this->createMock(PlatformAccount::class);
        $account->method('__get')->willReturnCallback(function ($key) {
            return match ($key) {
                'username' => null,
                'password' => 'testpass',
                'instance_url' => 'https://lemmy.test',
                default => null,
            };
        });

        try {
            app(LemmyAuthService::class)->getToken($account);
            $this->fail('Expected PlatformAuthException to be thrown');
        } catch (PlatformAuthException $e) {
            $this->assertEquals(PlatformEnum::LEMMY, $e->getPlatform());
        }
    }
}
