<?php

namespace App\Services;

use App\Models\Entry;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;

class XenforoApiService {

    private string $apiKey;
    private int $superUserId;
    private string $apiUrl;

    public function __construct(){
        $this->apiKey = config('services.xf_api.key');
        $this->superUserId = config('services.xf_api.user');
        $this->apiUrl = config('services.xf_api.url');
    }

    /**
     * @throws ConnectionException
     */
    private function get(string $endpoint, ?int $customUserId = null ): mixed
    {
        $response = Http::timeout(30)->withOptions(['verify' => false])->withHeaders([
            'XF-Api-Key' => $this->apiKey,
            'XF-Api-User' => $customUserId ?? $this->superUserId,
        ])->get("{$this->apiUrl}/{$endpoint}");

        if( !$response->ok() ) {
            \Illuminate\Support\Facades\Log::error("XF API error [{$response->status()}] on {$endpoint}: " . $response->body());
            return null;
        }

        return $response->json();
    }

    private function post(string $endpoint, ?int $customUserId = null, array $data = [] ): mixed
    {
        $response = Http::timeout(30)->withOptions(['verify' => false])->withHeaders([
            'XF-Api-Key' => $this->apiKey,
            'XF-Api-User' => $customUserId ?? $this->superUserId,
        ])->post("{$this->apiUrl}/{$endpoint}", $data);

        if( !$response->ok() ) {
            \Illuminate\Support\Facades\Log::error("XF API error [{$response->status()}] on {$endpoint}: " . $response->body());
            return null;
        }

        return $response->json();
    }

    private function delete(string $endpoint, ?int $customUserId = null, array $data = [] ): mixed
    {
        $response = Http::timeout(30)->withOptions(['verify' => false])->withHeaders([
            'XF-Api-Key' => $this->apiKey,
            'XF-Api-User' => $customUserId ?? $this->superUserId,
        ])->delete("{$this->apiUrl}/{$endpoint}", $data);

        if( !$response->ok() ) {
            \Illuminate\Support\Facades\Log::error("XF API error [{$response->status()}] on {$endpoint}: " . $response->body());
            return null;
        }

        return $response->json();
    }

    public function getUserAlerts(int $userId): mixed
    {
        if( app(XenforoService::class)->getXfUser($userId)?->alerts_unviewed > 0 ) {
            Cache::forget("xf_alerts_{$userId}");
        }

        return Cache::remember("xf_alerts_{$userId}", 60, function() use($userId) {
            return $this->get("alerts?page=1&cutoff=7days", $userId);
        });
    }

    public function markAllNotificationsRead(int $userId): void
    {
        Cache::forget("xf_alerts_{$userId}");
        $this->post("alerts/mark-all", $userId );
    }

    public function getConversations(int $userId): mixed
    {
        return Cache::remember("xf_conversations_{$userId}", 60, function() use($userId) {
            return $this->get("conversations?page=1&receiver_id={$userId}", $userId);
        });
    }

    public function createConversation( array $userIdList, string $title, string $message, bool $conversationOpen, bool $openInvite ): bool
    {
        $response = $this->post("conversations",
            data: ['recipient_ids' => $userIdList, 'title' => $title, 'message' => $message, 'open_invite' => $openInvite, 'conversation_open' => $conversationOpen]
        );
        return $response['success'] ?? false;
    }

    public function createCommentsThread( Entry|News $entry ): bool
    {
        if( !$entry->comments_thread_id || $entry->comments_thread_id <= 0 ){
            $data = [
                'node_id' => config('xenforo.comments_node_id'),
                'title' => $entry->complete_title,
                'message' => $entry->description,
                'prefix_id' => config('xenforo.comments_prefixes')[$entry->type] ?? 1,
                'custom_fields' => [ 'entry_id' => $entry->id ],
                'discussion_open' => true,
            ];

            // TODO: Flag must be removed.
            $response = $this->post("threads?api_bypass_permissions=true", config('xenforo.bot_user_id'), $data );
            if( $response['success'] === true ){
                $commentsThreadId = $response['thread']['thread_id'];
                $entry->update(['comments_thread_id' => $commentsThreadId]);
                return true;
            }
        }

        return false;
    }

    /**
     * @throws ConnectionException
     */
    public function getThreadPosts(int $threadId, int $page = 1 ): array
    {
        $response = $this->get("threads/{$threadId}/posts?page=$page");
        if( !isset( $response['posts'] ) || $response['posts'] === [] )
            return [ 'posts' => [], 'pagination' => null ];

        return $response;
    }

    public function updateEntriesCount(int $entryCount, int $userId): bool
    {
        $response = $this->post("romhackplaza_entry/update_entry_count", data: ['count' => $entryCount, 'user_id' => $userId] );
        return $response['success'] ?? false;
    }

    public function featuredRequest( Entry $entry ): bool
    {
        $response = $this->post("romhackplaza_entry/featured", data: [
           'entry_id' => $entry->id, 'user_id' => $entry->user_id, 'entry_title' => $entry->complete_title ?? $entry->title,
        ]);
        return $response['success'] ?? false;
    }

    public function deleteThreadWithEntry(int $threadId): bool
    {
        return (bool) $this->delete( "threads/{$threadId}", data: ['reason' => "Deletion with entry." ] );
    }

    public function restoreThreadWithEntry(int $threadId): bool
    {
        return (bool) $this->post("threads/{$threadId}/undelete" );
    }

    public function _migrateUser(array $data): array
    {
        $response = $this->post("migrate/user", data: $data );
        if( !$response || !$response['success'] )
            return [false,false];

        return [ $response['user_id'] ?? false, $response['password_set'] ?? false ];
    }

}
