<?php

namespace App\Http\Controllers;

use App\Models\Project;
use App\Services\MediaStorage;
use App\Support\AppMode;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class MediaController extends Controller
{
    public function store(Request $request, Project $project): JsonResponse
    {
        $this->authorizeProject($request, $project);

        $data = $request->validate([
            // SVG is excluded — inline <script> in SVG is stored-XSS when the
            // file is served off the public storage symlink.
            'file' => ['required', 'file', 'mimes:png,jpg,jpeg,webp,gif', 'max:20480'],
        ]);

        $file = $data['file'];

        // Per-plan storage cap: 402 when the pending upload would push the
        // user past their plan's `storage_bytes_limit`. Self-hosted installs
        // return null (unlimited) from `storageBytesLimit()` —
        // `canUpload()` short-circuits to true so the script-buyer flow is
        // unchanged. Fires AFTER auth/throttle but BEFORE the upload commits
        // so a denied request never lands bytes on disk.
        if (! $request->user()->canUpload((int) $file->getSize())) {
            return response()->json([
                'message' => 'Storage limit reached for your plan.',
                'plan_key' => $request->user()->activePlan()?->key,
                'pricing_url' => '/pricing',
                'used_bytes' => $request->user()->storageBytesUsed(),
                'limit_bytes' => $request->user()->storageBytesLimit(),
            ], 402);
        }

        // Prefer the mime-sniffed extension; never trust the client-supplied
        // original extension. `mimes:` already rejects anything outside the
        // whitelist, so $file->extension() always resolves for a validated
        // upload — the 'png' fallback is belt-and-suspenders only.
        $ext = strtolower($file->extension()) ?: 'png';
        $name = Str::uuid()->toString().'.'.$ext;

        $path = MediaStorage::put(
            $file,
            "projects/{$project->id}",
            $name,
            [
                'owner_type' => 'project',
                'owner_id' => $project->id,
                'purpose' => 'screen-image',
            ],
        );

        $size = getimagesize($file->getRealPath());
        [$width, $height] = is_array($size) ? [$size[0], $size[1]] : [null, null];

        return response()->json([
            'storagePath' => $path,
            'url' => MediaStorage::url($path),
            'width' => $width,
            'height' => $height,
        ]);
    }

    private function authorizeProject(Request $request, Project $project): void
    {
        if (AppMode::isSelfHosted()) {
            abort_unless($project->tenant_id === null, 404);

            return;
        }

        abort_unless($project->tenant_id === $request->user()->tenant_id, 404);

        // Per-project visibility (Team Workspaces P3d / Δ23). MediaController
        // authorizes independently of ProjectController, so the grant check
        // must be repeated here. 404 (not 403) — don't leak existence.
        abort_unless($request->user()->canAccessProject($project), 404);
    }
}
