<?php

use CodeIgniter\HTTP\Files\UploadedFile;

/**
 * Extension-based MIME type lookup for a file already on disk (a stored
 * logo, an uploaded staff document) — used wherever this app needs to
 * set a real Content-Type header, instead of PHP's mime_content_type().
 * That function requires the `fileinfo` extension, which isn't reliably
 * enabled on every host (confirmed missing on the live shared-hosting
 * deploy — every direct mime_content_type() call there was a hard fatal
 * error, "Call to undefined function"). Covers exactly the file types
 * this app itself ever writes via handle_image_upload()/
 * handle_document_upload() below — not a general-purpose MIME sniffer,
 * just enough to never depend on a PHP extension the host may not have.
 */
if (! function_exists('guess_mime_type')) {
    function guess_mime_type(string $path): string
    {
        $types = [
            'jpg'  => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'png'  => 'image/png',
            'webp' => 'image/webp',
            'gif'  => 'image/gif',
            'pdf'  => 'application/pdf',
            'doc'  => 'application/msword',
            'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        ];

        $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));

        return $types[$extension] ?? 'application/octet-stream';
    }
}

/**
 * Shared image-upload handling — used by both the tenant's own logo
 * (Settings > Hotel Information) and menu item photos (Restaurant >
 * Menu Items). One helper rather than duplicating the same validate/
 * move/return-a-relative-path logic in two controllers.
 *
 * Files land under writable/uploads/{subdir}/ with a random name (never
 * the client-supplied filename — avoids path traversal and collisions).
 * Returns the relative path to store in the DB (e.g. "logos/abc123.png"),
 * or null if no file was submitted. Throws nothing — an invalid upload
 * (wrong type, too large, corrupt) is reported via the returned array's
 * 'error' key so the caller can flash it, same tolerance-of-failure
 * pattern as the rest of this app's optional integrations.
 *
 * @return array{path: ?string, error: ?string}
 */
if (! function_exists('handle_image_upload')) {
    function handle_image_upload(?UploadedFile $file, string $subdir): array
    {
        if ($file === null || ! $file->isValid() || $file->getError() === UPLOAD_ERR_NO_FILE) {
            return ['path' => null, 'error' => null];
        }

        if ($file->hasMoved()) {
            return ['path' => null, 'error' => 'Upload already processed.'];
        }

        $allowedMimes = ['image/jpeg', 'image/png', 'image/webp'];

        if (! in_array($file->getMimeType(), $allowedMimes, true)) {
            return ['path' => null, 'error' => 'Only JPG, PNG, or WEBP images are allowed.'];
        }

        if ($file->getSize() > 2 * 1024 * 1024) {
            return ['path' => null, 'error' => 'Image must be 2MB or smaller.'];
        }

        $targetDir = WRITEPATH . 'uploads/' . trim($subdir, '/');

        if (! is_dir($targetDir)) {
            mkdir($targetDir, 0755, true);
        }

        $newName = $file->getRandomName();
        $file->move($targetDir, $newName);

        return ['path' => trim($subdir, '/') . '/' . $newName, 'error' => null];
    }
}

/**
 * Sibling to handle_image_upload() for employment documents (ID copies,
 * contracts, certificates) — a different allowlist (PDF/DOC/DOCX in
 * addition to images) and a larger size cap, since these aren't
 * decorative photos. Also returns the client's original filename (image
 * uploads never needed this — a logo/photo is never "downloaded" by
 * name — but a document should offer a readable filename, not the
 * randomized on-disk name, when a manager downloads it later).
 *
 * Storage/randomized-naming is otherwise identical to
 * handle_image_upload() (same writable/uploads/{subdir}/ root, same
 * collision/traversal-avoiding random name) — kept as a separate
 * function rather than parameterizing the existing one so each one's
 * allowlist/size-cap stays simple to read, not threaded through
 * conditionals for two different use cases.
 *
 * @return array{path: ?string, originalName: ?string, error: ?string}
 */
if (! function_exists('handle_document_upload')) {
    function handle_document_upload(?UploadedFile $file, string $subdir): array
    {
        if ($file === null || ! $file->isValid() || $file->getError() === UPLOAD_ERR_NO_FILE) {
            return ['path' => null, 'originalName' => null, 'error' => null];
        }

        if ($file->hasMoved()) {
            return ['path' => null, 'originalName' => null, 'error' => 'Upload already processed.'];
        }

        $allowedMimes = [
            'application/pdf',
            'application/msword',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'image/jpeg',
            'image/png',
        ];

        if (! in_array($file->getMimeType(), $allowedMimes, true)) {
            return ['path' => null, 'originalName' => null, 'error' => 'Only PDF, Word documents, JPG, or PNG files are allowed.'];
        }

        if ($file->getSize() > 10 * 1024 * 1024) {
            return ['path' => null, 'originalName' => null, 'error' => 'File must be 10MB or smaller.'];
        }

        $targetDir = WRITEPATH . 'uploads/' . trim($subdir, '/');

        if (! is_dir($targetDir)) {
            mkdir($targetDir, 0755, true);
        }

        $originalName = $file->getClientName();
        $newName      = $file->getRandomName();
        $file->move($targetDir, $newName);

        return ['path' => trim($subdir, '/') . '/' . $newName, 'originalName' => $originalName, 'error' => null];
    }
}
