<?php

namespace FriendsOfBotble\Comment\Support;

use Botble\Base\Contracts\BaseModel;
use Botble\Captcha\Facades\Captcha;
use FriendsOfBotble\Comment\Enums\CommentStatus;
use FriendsOfBotble\Comment\Models\Comment;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class CommentHelper
{
    public static function isEnableReCaptcha(): bool
    {
        return is_plugin_active('captcha') && setting('fob_comment_enable_recaptcha', false) && Captcha::isEnabled();
    }

    public static function commentMustBeModerated(): bool
    {
        return setting('fob_comment_comment_moderation', false);
    }

    public static function getCommentOrder(): string
    {
        $order = setting('fob_comment_comment_order', 'asc');

        if (! in_array($order, ['asc', 'desc'])) {
            $order = 'asc';
        }

        return $order;
    }

    public static function isShowCommentCookieConsent(): bool
    {
        return setting('fob_comment_show_comment_cookie_consent', true);
    }

    public static function isAutoFillCommentForm(): bool
    {
        return setting('fob_comment_auto_fill_comment_form', true);
    }

    public static function isShowWebsiteField(): bool
    {
        return setting('fob_comment_show_website_field', true);
    }

    public static function isDisplayAdminBadge(): bool
    {
        return setting('fob_comment_display_admin_badge', true);
    }

    public static function isEmailOptional(): bool
    {
        return setting('fob_comment_email_optional', false);
    }

    public static function getRateLimitSeconds(): int
    {
        return (int) setting('fob_comment_rate_limit_seconds', 15);
    }

    public static function isAllowAuthorDelete(): bool
    {
        return setting('fob_comment_allow_author_delete', false);
    }

    public static function isGuestCommentDisabled(): bool
    {
        return setting('fob_comment_disable_guest_comment', false);
    }

    public static function getAvailableAuthGuards(): array
    {
        $guards = array_keys(config('auth.guards', []));
        $excludedGuards = ['web', 'api', 'sanctum'];

        return array_values(array_filter($guards, fn ($guard) => ! in_array($guard, $excludedGuards)));
    }

    public static function hasMultipleAuthGuards(): bool
    {
        return count(self::getAvailableAuthGuards()) > 0;
    }

    public static function getAuthorizedUser(): ?Authenticatable
    {
        // Get all configured guards except web and api
        $guards = array_keys(config('auth.guards', []));
        $excludedGuards = ['web', 'api', 'sanctum'];

        foreach ($guards as $guard) {
            if (in_array($guard, $excludedGuards)) {
                continue;
            }

            if (auth($guard)->check()) {
                return auth($guard)->user();
            }
        }

        return null;
    }

    public static function preparedDataForFill(): array
    {
        if (! CommentHelper::isAutoFillCommentForm()) {
            return [];
        }

        $data = [];

        $user = self::getAuthorizedUser();

        if ($user) {
            $data['name'] = $user->name;
            $data['email'] = $user->email;
        }

        return apply_filters('fob_comment_prepare_comment_data', $data);
    }

    public static function getCommentsCount(BaseModel $reference): int
    {
        $counter = app('fob.comments.counter');

        if (isset($counter[$reference::class][$reference->getKey()])) {
            return $counter[$reference->getKey()];
        }

        $counter = static::loadCommentsCount([$reference]);

        return $counter[$reference::class][$reference->getKey()] ?? 0;
    }

    public static function loadCommentsCount(Collection|array $collect): array
    {
        $counter = app('fob.comments.counter');

        if (empty($collect)) {
            return $counter;
        }

        $query = Comment::query();

        $query
            ->select(['reference_type', 'reference_id', DB::raw('count(*) as total')])
            ->where('status', CommentStatus::APPROVED);

        foreach ($collect as $reference) {
            $query->orWhere(function (Builder $query) use ($reference): void {
                $query
                    ->where('reference_type', $reference::class)
                    ->where('reference_id', $reference->getKey());
            });
        }

        $query->groupBy(['reference_type', 'reference_id']);

        $result = $query->get();

        foreach ($result as $item) {
            $counter[$item->reference_type][$item->reference_id] = $item->total;
        }

        app()->instance('fob.comments.counter', $counter);

        return $counter;
    }
}
