<?php

namespace App\Jobs;

use App\Enums\NotificationSeverityEnum;
use App\Enums\NotificationTypeEnum;
use App\Models\Notification;
use App\Models\PlatformAccount;
use App\Modules\Lemmy\Services\LemmyApiService;
use App\Services\Notification\NotificationService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Throwable;

class CheckPlatformCredentialsJob implements ShouldQueue
{
    use Queueable;

    public function handle(NotificationService $notificationService): void
    {
        $accounts = PlatformAccount::where('is_active', true)->get();

        foreach ($accounts as $account) {
            $this->check($account, $notificationService);
        }
    }

    private function check(PlatformAccount $account, NotificationService $notificationService): void
    {
        if ($this->canLogIn($account)) {
            $account->recordCredentialCheckPassed();

            return;
        }

        $wasUnhealthy = $account->isUnhealthy();
        $account->recordCredentialCheckFailed();

        if (! $wasUnhealthy && $account->refresh()->isUnhealthy()) {
            $this->notify($account, $notificationService);
        }
    }

    private function canLogIn(PlatformAccount $account): bool
    {
        try {
            return $this->makeApiService($account)->login($account->username, $account->password) !== null;
        } catch (Throwable) {
            return false;
        }
    }

    protected function makeApiService(PlatformAccount $account): LemmyApiService
    {
        return new LemmyApiService($account->instance_url);
    }

    private function notify(PlatformAccount $account, NotificationService $notificationService): void
    {
        $alreadyNotified = Notification::query()
            ->where('type', NotificationTypeEnum::CREDENTIAL_EXPIRED)
            ->where('notifiable_type', $account->getMorphClass())
            ->where('notifiable_id', $account->getKey())
            ->unread()
            ->exists();

        if ($alreadyNotified) {
            return;
        }

        $notificationService->send(
            type: NotificationTypeEnum::CREDENTIAL_EXPIRED,
            severity: NotificationSeverityEnum::ERROR,
            title: "Credentials failed for {$account->username}",
            message: "Could not log in to {$account->instance_url} after ".PlatformAccount::FAILURES_BEFORE_UNHEALTHY.' attempts. Publishing to this account will fail until it is fixed.',
            notifiable: $account,
        );
    }
}
