<?php

namespace App\Support;

use Illuminate\Support\Str;

class JobText
{
    public static function clean(?string $value, ?int $limit = null): string
    {
        if (! filled($value)) {
            return '';
        }

        $text = html_entity_decode((string) $value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $text = preg_replace('/<li\b[^>]*>/i', "\n- ", $text) ?? $text;
        $text = preg_replace('/<(br|\/p|\/div|\/li|\/h[1-6])\b[^>]*>/i', "\n", $text) ?? $text;
        $text = strip_tags($text);
        $text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $text = preg_replace('/https?:\/\/[^\s<>"\']+/i', '', $text) ?? $text;
        $text = preg_replace('/\bTo apply:\s*/i', '', $text) ?? $text;
        $text = preg_replace('/^\s*(URL|To apply):\s*$/mi', '', $text) ?? $text;
        $text = preg_replace('/[ \t]+/', ' ', $text) ?? $text;
        $text = preg_replace("/\n[ \t]+/", "\n", $text) ?? $text;
        $text = preg_replace("/\n{3,}/", "\n\n", $text) ?? $text;
        $text = trim($text);

        return $limit ? Str::limit($text, $limit) : $text;
    }

    public static function excerpt(?string $value, int $limit = 260): string
    {
        return self::clean($value, $limit);
    }

    /**
     * @return array<int, string>
     */
    public static function paragraphs(?string $value): array
    {
        return collect(preg_split("/\n+/", self::clean($value)) ?: [])
            ->map(fn (string $paragraph): string => trim($paragraph))
            ->filter()
            ->values()
            ->all();
    }

    /**
     * @return array{currency: ?string, min: ?int, max: ?int}
     */
    public static function salaryRange(?string $value): array
    {
        $text = self::clean($value);

        if ($text === '') {
            return ['currency' => null, 'min' => null, 'max' => null];
        }

        $patterns = [
            '/(?:USD|US dollars?|\$)\s*([0-9][0-9,]*(?:\.\d+)?\s*[kK]?)\s*(?:USD|US)?\s*(?:-|–|—|to|and)\s*(?:USD|US dollars?|\$)?\s*([0-9][0-9,]*(?:\.\d+)?\s*[kK]?)/i',
            '/([0-9][0-9,]*(?:\.\d+)?\s*[kK]?)\s*(?:-|–|—|to|and)\s*([0-9][0-9,]*(?:\.\d+)?\s*[kK]?)\s*(?:USD|US dollars?)/i',
        ];

        foreach ($patterns as $pattern) {
            if (preg_match($pattern, $text, $matches) === 1) {
                $min = self::moneyAmount($matches[1] ?? null);
                $max = self::moneyAmount($matches[2] ?? null);

                if ($min !== null && $max !== null) {
                    if ($min > $max) {
                        [$min, $max] = [$max, $min];
                    }

                    return ['currency' => 'USD', 'min' => $min, 'max' => $max];
                }
            }
        }

        if (preg_match('/(?:up to|max(?:imum)?|top performers earn)\s*(?:USD|US dollars?|\$)\s*([0-9][0-9,]*(?:\.\d+)?\s*[kK]?)/i', $text, $matches) === 1) {
            return ['currency' => 'USD', 'min' => null, 'max' => self::moneyAmount($matches[1] ?? null)];
        }

        if (preg_match('/(?:from|starting at|minimum|base(?: pay| salary)?)\s*(?:USD|US dollars?|\$)\s*([0-9][0-9,]*(?:\.\d+)?\s*[kK]?)/i', $text, $matches) === 1) {
            return ['currency' => 'USD', 'min' => self::moneyAmount($matches[1] ?? null), 'max' => null];
        }

        return ['currency' => null, 'min' => null, 'max' => null];
    }

    private static function moneyAmount(?string $value): ?int
    {
        if (! filled($value)) {
            return null;
        }

        $normalized = strtolower(str_replace([',', ' '], '', (string) $value));
        $multiplier = str_ends_with($normalized, 'k') ? 1000 : 1;
        $normalized = rtrim($normalized, 'k');

        if (! is_numeric($normalized)) {
            return null;
        }

        return (int) round((float) $normalized * $multiplier);
    }
}
