<?php

namespace WPSN\Modules\Media;

defined('ABSPATH') || exit;

/**
 * Simple, local (no external calls) alt text suggestion engine.
 *
 * Priority:
 * 1) Caption
 * 2) Attachment title
 * 3) Cleaned filename
 */
final class LocalAltSuggestionEngine
{
    /**
     * Generate an alt text suggestion for an attachment.
     */
    public function suggest(int $attachmentId, int $maxLength = 125): string
    {
        if ($attachmentId <= 0) {
            return '';
        }

        $post = get_post($attachmentId);
        if (!$post || !isset($post->post_type) || (string) $post->post_type !== 'attachment') {
            return '';
        }

        $mime = (string) get_post_mime_type($attachmentId);
        if ($mime === '' || strpos($mime, 'image/') !== 0) {
            return '';
        }

        $caption = isset($post->post_excerpt) ? (string) $post->post_excerpt : '';
        $title   = (string) get_the_title($attachmentId);
        $fileAlt = $this->filenameToAlt($this->extractFilename($attachmentId));

        $candidate = '';
        foreach ([$caption, $title, $fileAlt] as $value) {
            $value = $this->toPlainText($value);
            if ($value !== '') {
                $candidate = $value;
                break;
            }
        }

        if ($candidate === '') {
            return '';
        }

        $candidate = $this->truncateChars($candidate, $maxLength);
        return trim($candidate);
    }

    private function extractFilename(int $attachmentId): string
    {
        $rel = (string) get_post_meta($attachmentId, '_wp_attached_file', true);
        $file = $rel !== '' ? $rel : (string) get_attached_file($attachmentId);
        if ($file === '') {
            return '';
        }

        $base = basename($file);
        $base = rawurldecode($base);
        return (string) $base;
    }

    private function filenameToAlt(string $filename): string
    {
        if ($filename === '') {
            return '';
        }

        $name = (string) pathinfo($filename, PATHINFO_FILENAME);
        $name = str_replace(['_', '-'], ' ', $name);

        // Strip common WP suffixes.
        $name = preg_replace('/-\d{2,4}x\d{2,4}$/', '', (string) $name);
        $name = preg_replace('/-scaled$/', '', (string) $name);
        $name = preg_replace('/-rotated$/', '', (string) $name);

        // Strip trailing purely numeric token (common camera/file sequences).
        $name = preg_replace('/\s*\d{2,}$/', '', (string) $name);

        $name = preg_replace('/\s+/', ' ', (string) $name);
        return trim((string) $name);
    }

    private function toPlainText(string $text): string
    {
        $t = wp_strip_all_tags($text);
        $t = html_entity_decode($t, ENT_QUOTES, 'UTF-8');
        $t = preg_replace('/\s+/', ' ', (string) $t);
        return trim((string) $t);
    }

    private function truncateChars(string $text, int $maxChars): string
    {
        $maxChars = max(0, $maxChars);
        if ($maxChars === 0) {
            return '';
        }

        if (function_exists('mb_strlen') && function_exists('mb_substr')) {
            if ((int) mb_strlen($text) > $maxChars) {
                return (string) mb_substr($text, 0, $maxChars);
            }
            return $text;
        }

        if (strlen($text) > $maxChars) {
            return substr($text, 0, $maxChars);
        }

        return $text;
    }
}
