<?php
namespace App\Controllers;

/**
 * FileServe — serves files stored in WRITEPATH/uploads/ securely.
 * Replaces direct public access to uploaded files.
 *
 * Route: GET file/(:segment)/(:any)  → FileServe::serve/$1/$2
 * Example: /file/workorders/abc123.pdf
 */
class FileServe extends BaseController
{
    private const MIME_MAP = [
        'pdf'  => 'application/pdf',
        'jpg'  => 'image/jpeg',
        'jpeg' => 'image/jpeg',
        'png'  => 'image/png',
        'gif'  => 'image/gif',
        'webp' => 'image/webp',
        'svg'  => 'image/svg+xml',
        'doc'  => 'application/msword',
        'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'xls'  => 'application/vnd.ms-excel',
        'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    ];

    /**
     * Serve a file from WRITEPATH/uploads/{subDir}/{filename}
     * @param string $subDir  e.g. "workorders", "receipts", "logos"
     * @param string $filename
     */
    public function serve(string $subDir, string $filename): \CodeIgniter\HTTP\Response
    {
        // Strip path traversal attempts
        $subDir   = basename($subDir);
        $filename = basename($filename);

        $path = WRITEPATH . 'uploads/' . $subDir . '/' . $filename;

        // Security: verify path is inside uploads directory
        $realPath    = realpath($path);
        $uploadsRoot = realpath(WRITEPATH . 'uploads/');

        if (!$realPath || !$uploadsRoot || strpos($realPath, $uploadsRoot) !== 0) {
            throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
        }

        if (!file_exists($realPath)) {
            throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
        }

        // Role-based access: receipts and finance files require finance role
        $role = session()->get('user_role');
        if (in_array($subDir, ['receipts', 'invoices']) && !in_array($role, ['super_admin','facility_manager','finance_manager','finance_user'])) {
            return $this->response->setStatusCode(403)->setBody('Access denied.');
        }

        $ext  = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
        $mime = self::MIME_MAP[$ext] ?? mime_content_type($realPath) ?: 'application/octet-stream';

        // Decide inline vs download
        $inline = in_array($mime, ['image/jpeg','image/png','image/gif','image/webp','image/svg+xml','application/pdf']);

        return $this->response
            ->setHeader('Content-Type', $mime)
            ->setHeader('Content-Length', (string)filesize($realPath))
            ->setHeader('Content-Disposition', ($inline ? 'inline' : 'attachment') . '; filename="' . $filename . '"')
            ->setHeader('Cache-Control', 'private, max-age=3600')
            ->setHeader('X-Content-Type-Options', 'nosniff')
            ->setBody(file_get_contents($realPath));
    }
}
