<?php

namespace FSPoster\App\Watermark\App;

use Exception;
use FSPoster\App\Providers\Core\Settings;
use FSPoster\App\Providers\License\PlanFeatures;
use FSPoster\App\Providers\Schedules\ScheduleObject;
use FSPoster\App\Watermark\Api\Api;
use FSPoster\App\Watermark\App\DTOs\Response\WatermarkUsageResult;
use FSPoster\GuzzleHttp\Exception\GuzzleException;

class Listener
{
    /**
     * @throws GuzzleException
     * @throws Exception
     */
    public static function applyWatermark(array $mediaListToUpload, ScheduleObject $scheduleObj): array
    {
        if (!Settings::get('watermark_enabled', false) || $scheduleObj->readOnlyMode) {
            return $mediaListToUpload;
        }

        $rules = self::getEnabledRules();

        if (empty($rules)) {
            return $mediaListToUpload;
        }

        $rules = self::applyShortcodesToRules($rules, $scheduleObj);
        $socialNetwork = $scheduleObj->getSocialNetwork();
        $shareOnFail = Settings::get('watermark_rendering_fails', 'original') === 'original';
        $api = new Api();
        $usage = $api->getWatermarkUsage();

        $watermarkedMediaList = [];

        foreach ($mediaListToUpload as $media) {
            $matchedRules = self::getMatchingRules($media, $socialNetwork, $rules);

            if (empty($matchedRules)) {
                $watermarkedMediaList[] = $media;
                 break;
            }

            if (! self::isWithinUsageLimit($media['type'], $usage)) {
                if (!$shareOnFail) {
                    throw new Exception(fsp__('Watermark usage limit reached'));
                }
                $watermarkedMediaList[] = $media;
                break;
            }

            try {
                $result = $api->processMedia($media, $socialNetwork, $matchedRules);
                $usage->incrementForType($media['type']);

                $watermarkedMediaList[] = $result;
            } catch (Exception $e) {
                if (!$shareOnFail) {
                    throw $e;
                }

                $watermarkedMediaList[] = $media;
            }
        }
        return $watermarkedMediaList;
    }

    private static function applyShortcodesToRules(array $rules, ScheduleObject $scheduleObj): array
    {
        $result = [];
        foreach ($rules as $rule) {
            if ($rule['applyType'] === 'text' && !empty($rule['options']['textValue'])) {
                $rule['options']['textValue'] = $scheduleObj->replaceShortCodes($rule['options']['textValue'], false);
            }
            $result[] = $rule;

        }
        return $result;
    }

    private static function getEnabledRules(): array
    {
        $rules = Settings::get('watermark_rules');

        if (!is_array($rules)) {
            return [];
        }

        return array_filter($rules, fn($rule) => !empty($rule['enabled']));
    }

    private static function isWithinUsageLimit(string $mediaType, WatermarkUsageResult $usage): bool
    {
        $featureSlug = 'watermark_' . $mediaType;
        $limit = PlanFeatures::getFeatureLimit($featureSlug);

        if ($limit === null) {
            return true;
        }

        return $usage->countForType($mediaType) < $limit;
    }

    private static function getMatchingRules(array $media, string $socialNetwork, array $rules): array
    {
        return array_filter($rules, function ($rule) use ($media, $socialNetwork) {
            $filters = $rule['filters'] ?? [];

            if (empty($filters) || !in_array($media['type'], $filters['mediaTypes'] ?? [])) {
                return false;
            }

            if (!empty($filters['socialNetworks'] ?? []) && !in_array($socialNetwork, $filters['socialNetworks'])) {
                return false;
            }

            return true;
        });
    }
}