<?php
namespace EasyChat\Library\Messenger;

use EasyChat\Library\AttachmentPolicy;






class OutboundAttachmentLink {

    const DEFAULT_TTL_SECONDS = 3600;
    const DEFAULT_DOCUMENT_TTL_SECONDS = 604800;

    public static function imageUrl(int $chat_id, string $filename, string $secret, int $ttl_seconds = self::DEFAULT_TTL_SECONDS): string {
        $filename = basename(trim($filename));
        $secret = trim($secret);
        if ($chat_id <= 0 || $filename === '' || $secret === '') {
            return '';
        }

        $expires = time() + max(60, min(86400, $ttl_seconds));
        $signature = self::sign($chat_id, $filename, $expires, $secret);
        return HTTP_SERVER . 'index.php?route=widget/outboundImage'
            . '&chat_id=' . (int)$chat_id
            . '&file=' . rawurlencode($filename)
            . '&expires=' . $expires
            . '&sig=' . rawurlencode($signature);
    }

    public static function documentUrl(int $chat_id, string $filename, string $display_name, string $secret, int $ttl_seconds = self::DEFAULT_DOCUMENT_TTL_SECONDS): string {
        $filename = self::safeDownloadName($filename);
        $display_name = self::safeDownloadName($display_name);
        $secret = trim($secret);
        if ($chat_id <= 0 || $filename === '' || $secret === '') {
            return '';
        }

        if ($display_name === '') {
            $display_name = $filename;
        }

        $expires = time() + max(300, min(self::DEFAULT_DOCUMENT_TTL_SECONDS, $ttl_seconds));
        $signature = self::signDocument($chat_id, $filename, $display_name, $expires, $secret);
        return HTTP_SERVER . 'index.php?route=widget/outboundFile'
            . '&chat_id=' . (int)$chat_id
            . '&file=' . rawurlencode($filename)
            . '&name=' . rawurlencode($display_name)
            . '&expires=' . $expires
            . '&sig=' . rawurlencode($signature);
    }

    public static function verify(int $chat_id, string $filename, int $expires, string $signature, string $secret): bool {
        $filename = self::safeDownloadName($filename);
        $signature = trim($signature);
        $secret = trim($secret);
        if ($chat_id <= 0 || $filename === '' || $signature === '' || $secret === '') {
            return false;
        }
        if ($expires < time() || $expires > time() + 86400) {
            return false;
        }

        return hash_equals(self::sign($chat_id, $filename, $expires, $secret), $signature);
    }

    public static function verifyDocument(int $chat_id, string $filename, string $display_name, int $expires, string $signature, string $secret): bool {
        $filename = self::safeDownloadName($filename);
        $display_name = self::safeDownloadName($display_name);
        $signature = trim($signature);
        $secret = trim($secret);
        if ($display_name === '') {
            $display_name = $filename;
        }
        if ($chat_id <= 0 || $filename === '' || $signature === '' || $secret === '') {
            return false;
        }
        if ($expires < time() || $expires > time() + self::DEFAULT_DOCUMENT_TTL_SECONDS) {
            return false;
        }

        return hash_equals(self::signDocument($chat_id, $filename, $display_name, $expires, $secret), $signature);
    }

    public static function isAllowedImagePath(string $path): bool {
        if (!is_file($path)) {
            return false;
        }
        $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
        $mime = AttachmentPolicy::detectMime($path, $extension);
        return AttachmentPolicy::isImageExtension($extension, true)
            && AttachmentPolicy::isImageMime($mime, true);
    }

    public static function isAllowedDocumentPath(string $path): bool {
        if (!is_file($path)) {
            return false;
        }
        $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
        if (!AttachmentPolicy::isDocumentExtension($extension)) {
            return false;
        }
        $size = (int)filesize($path);
        $max_mb = max(1, (int)ceil(max(1, $size) / 1024 / 1024));
        $validation = AttachmentPolicy::validateDocumentFile($path, basename($path), $size, $max_mb);
        return !empty($validation['success']);
    }

    public static function safeDownloadName(string $value): string {
        $value = basename(trim($value));
        return preg_replace('/[\x00-\x1F\x7F]+/', '_', $value) ?? '';
    }

    private static function sign(int $chat_id, string $filename, int $expires, string $secret): string {
        return hash_hmac('sha256', (int)$chat_id . '|' . self::safeDownloadName($filename) . '|' . (int)$expires, $secret);
    }

    private static function signDocument(int $chat_id, string $filename, string $display_name, int $expires, string $secret): string {
        return hash_hmac(
            'sha256',
            'document|' . (int)$chat_id . '|' . self::safeDownloadName($filename) . '|' . self::safeDownloadName($display_name) . '|' . (int)$expires,
            $secret
        );
    }
}
