<?php

namespace WPSN\Modules\Media;

defined('ABSPATH') || exit;

/**
 * Local (rule-based) filename suggestions for image attachments.
 *
 * We keep this intentionally simple and safe:
 * - Derive a base name from attachment title (fallback to parent title, then current filename)
 * - Sanitize via WordPress sanitize_file_name()
 * - Preserve the current extension
 * - Ensure uniqueness in the current upload subdirectory with wp_unique_filename()
 */
final class LocalFilenameSuggestionEngine
{
    /**
     * @return array{basename:string,rel_path:string,dir_rel:string,ext:string}|null
     */
    public function suggest(int $attachmentId, int $maxBaseLen = 80): ?array
    {
        $post = get_post($attachmentId);
        if (!$post || (string) ($post->post_type ?? '') !== 'attachment') {
            return null;
        }

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

        $abs = (string) get_attached_file($attachmentId);
        if ($abs === '') {
            return null;
        }

        $uploads = wp_upload_dir();
        $basedir = isset($uploads['basedir']) ? (string) $uploads['basedir'] : '';
        if ($basedir === '') {
            return null;
        }

        $rel = (string) get_post_meta($attachmentId, '_wp_attached_file', true);
        if ($rel === '') {
            $rel = $this->relativeFromAbs($abs, $basedir);
        }
        $rel = ltrim(str_replace('\\', '/', $rel), '/');

        $dirRel = '';
        if ($rel !== '') {
            $dirRel = dirname($rel);
            if ($dirRel === '.' || $dirRel === DIRECTORY_SEPARATOR) {
                $dirRel = '';
            }
            $dirRel = trim(str_replace('\\', '/', $dirRel), '/');
        }

        $oldBasename = wp_basename($abs);
        $ext = strtolower((string) pathinfo($oldBasename, PATHINFO_EXTENSION));
        if ($ext === '') {
            $ext = strtolower((string) pathinfo($abs, PATHINFO_EXTENSION));
        }
        if ($ext === '') {
            return null;
        }

        $candidate = trim((string) get_the_title($attachmentId));
        if ($candidate === '' && !empty($post->post_parent)) {
            $candidate = trim((string) get_the_title((int) $post->post_parent));
        }
        if ($candidate === '') {
            $candidate = (string) pathinfo($oldBasename, PATHINFO_FILENAME);
        }

        $candidate = $this->toPlainText($candidate);

        // Remove possible extension from candidate.
        $candidate = (string) preg_replace('/\.[a-z0-9]{1,6}$/i', '', $candidate);

        $candidate = trim($candidate);
        if ($candidate === '') {
            $candidate = 'image-' . $attachmentId;
        }

        $base = sanitize_file_name($candidate);
        $base = (string) preg_replace('/\.[a-z0-9]{1,6}$/i', '', $base);
        $base = trim((string) preg_replace('/\-+/', '-', (string) str_replace('_', '-', $base)));

        if ($base === '' || $base === '-' || $base === '.') {
            $base = 'image-' . $attachmentId;
        }

        $maxBaseLen = max(10, min(120, $maxBaseLen));
        if (function_exists('mb_strlen') && function_exists('mb_substr')) {
            if ((int) mb_strlen($base) > $maxBaseLen) {
                $base = (string) mb_substr($base, 0, $maxBaseLen);
                $base = trim((string) preg_replace('/\-+$/', '', $base));
            }
        } else {
            if (strlen($base) > $maxBaseLen) {
                $base = substr($base, 0, $maxBaseLen);
                $base = trim((string) preg_replace('/\-+$/', '', $base));
            }
        }

        $filename = $base . '.' . $ext;

        $dirAbs = $basedir;
        if ($dirRel !== '') {
            $dirAbs = rtrim($basedir, '/\\') . '/' . $dirRel;
        }

        // Ensure uniqueness.
        $unique = wp_unique_filename($dirAbs, $filename);
        $unique = (string) $unique;

        $newRel = $dirRel !== '' ? $dirRel . '/' . $unique : $unique;
        $newRel = ltrim(str_replace('\\', '/', $newRel), '/');

        return [
            'basename' => $unique,
            'rel_path' => $newRel,
            'dir_rel' => $dirRel,
            'ext' => $ext,
        ];
    }

    private function relativeFromAbs(string $abs, string $basedir): string
    {
        $absN = str_replace('\\', '/', $abs);
        $baseN = rtrim(str_replace('\\', '/', $basedir), '/');
        if ($baseN !== '' && strpos($absN, $baseN) === 0) {
            $rel = substr($absN, strlen($baseN));
            $rel = ltrim((string) $rel, '/');
            return (string) $rel;
        }
        return '';
    }

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