<?php

namespace App\Libraries;

use CodeIgniter\Files\File;
use CodeIgniter\HTTP\Files\UploadedFile;

final class FinancialAttachmentService
{
    private const MAX_BYTES = 5242880;
    private const ALLOWED_MIMES = [
        'application/pdf',
        'image/jpeg',
        'image/png',
    ];
    private const ALLOWED_EXTENSIONS = [
        'jpg',
        'jpeg',
        'pdf',
        'png',
    ];

    public function saveUploadedFile($file, string $subdir): ?string
    {
        if (!$file instanceof UploadedFile) {
            return null;
        }

        if (!$file->isValid() || $file->hasMoved()) {
            return null;
        }

        $size = (int) ($file->getSize() ?? 0);
        if ($size <= 0) {
            return null;
        }

        $mime = strtolower((string) $file->getMimeType());
        $ext = strtolower((string) $file->getClientExtension());

        if (!in_array($mime, self::ALLOWED_MIMES, true) || !in_array($ext, self::ALLOWED_EXTENSIONS, true)) {
            throw new \RuntimeException('Unsupported file type. Use PDF, JPG, or PNG.');
        }

        if ($size > self::MAX_BYTES) {
            throw new \RuntimeException('File too large. Maximum size is 5 MB.');
        }

        $dir = $this->ensureSubdir($subdir);
        $name = $file->getRandomName();
        $file->move($dir, $name);

        return $name;
    }

    public function resolvePath(string $subdir, string $filename): ?string
    {
        $safeName = basename($filename);
        if ($safeName === '') {
            return null;
        }

        $path = $this->ensureSubdir($subdir) . DIRECTORY_SEPARATOR . $safeName;

        return is_file($path) ? $path : null;
    }

    public function ensureSubdir(string $subdir): string
    {
        $path = WRITEPATH . 'uploads' . DIRECTORY_SEPARATOR . trim($subdir, '/');
        if (!is_dir($path) && !mkdir($path, 0775, true) && !is_dir($path)) {
            throw new \RuntimeException('Unable to prepare upload directory.');
        }

        return $path;
    }

    public function detectMime(string $path): string
    {
        if (function_exists('finfo_open')) {
            $handle = finfo_open(FILEINFO_MIME_TYPE);
            if ($handle) {
                $mime = finfo_file($handle, $path);
                finfo_close($handle);
                if (is_string($mime) && $mime !== '') {
                    return $mime;
                }
            }
        }

        if (function_exists('mime_content_type')) {
            $mime = mime_content_type($path);
            if (is_string($mime) && $mime !== '') {
                return $mime;
            }
        }

        return 'application/octet-stream';
    }
}
