<?php

namespace App\Services\Settings\History;

use App\Http\Responses\ReportOutputData;
use App\Repositories\CommonFilterRepository;
use App\Repositories\Settings\History\ApiBlockedIpRepository;
use Exception;
use Illuminate\Support\Facades\Log;

class ApiBlockedIpsService
{
    /**
     * Constructs a new instance of the class.
     *
     * @param ApiBlockedIpRepository $repository       The ApiBlockedIpRepository object.
     * @param CommonFilterRepository $commonFilterRepository The CommonFilterRepository object.
     * @param ReportOutputData       $reportOutputData The ReportOutputData object.
     */
    public function __construct(
        protected ApiBlockedIpRepository $repository,
        protected CommonFilterRepository $commonFilterRepository,
        protected ReportOutputData $reportOutputData
    ) {}

    /**
     * Retrieves the data for the Report.
     *
     * @return array Returns an array containing the filtered API blocked IPs and the count.
     */
    public function data()
    {
        $query = $this->repository->getApiBlockedIp();
        $query = $this->filter($query);
        $count = $query->count();
        $data = $this->reportOutputData->getOutputData($query, ['updated_at' => 'desc']);

        return compact('data', 'count');
    }

    /**
     * Filters the given API blocked IPs based on the provided input data.
     *
     * @param array $apiBlockedIps The list of API blocked IPs to filter.
     * @param array $inputData The input data used for filtering.
     *
     * @return Query The filtered list of API blocked IPs.
     */
    public function filter($apiBlockedIps)
    {
        $inputData     =  request('form') ?? request()->all();
        $apiBlockedIps = $this->commonFilterRepository->searchToMultipleFields($apiBlockedIps, ['ip'], $inputData['searchText'] ?? '');

        return $apiBlockedIps;
    }

    /**
     * Retrieves the blocked IP data from the API.
     *
     * @param array $apiBlockedIps The array of API blocked IPs.
     * @param int   $start         The starting index for the parent data.
     * @param array $data          The existing data array.
     *
     * @return array The updated data array with nested IP data.
     */
    public function getReportData($rows, $start, $data)
    {
        $parentIndex = $start;

        foreach ($rows as $row) {
            $parentIndex++;
            $nestedData = $this->getNestedData($row, $parentIndex);
            $data[] = $nestedData;
        }

        return $data;
    }

    /**
     * Retrieves the nested data from the given API blocked IP object.
     *
     * @param object $apiBlockedIp The API blocked IP object.
     * @param int    $index        The index of the nested data.
     *
     * @return array The nested data array containing the dataId, id, ip, attempts, created_at, updated_at, and action.
     */
    public function getNestedData($apiBlockedIp, $index)
    {
        $nestedData = [];
        $nestedData['id'] = $index;
        $nestedData['ip'] = $apiBlockedIp->ip;
        $nestedData['blocked_at'] = $apiBlockedIp->blocked_at;
        $nestedData['action'] = "<a class='btn btn-link delete-apiBlockedIp' data-id='" . $apiBlockedIp->id . "' data-toggle='modal' data-target='#unblockIpModal'><i class='icon icon-delete-forever icon-lg'></i></a>";

        return $nestedData;
    }

    /**
     * Unblock an IP address.
     *
     * @param int $id The ID of the IP address to unblock.
     *
     * @throws Exception If an error occurs during the unblocking process.
     * @return bool Returns true if the IP address was successfully unblocked, false otherwise.
     */
    public function unblockIp($id)
    {
        try {
            $this->repository->releaseApiBlockedIp($id);

            return true;
        } catch (Exception $e) {
            Log::error($e->getMessage());

            return false;
        }
    }
}
