<?php

declare(strict_types=1);

use App\Models\Artwork;
use App\Models\User;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\DB;

beforeEach(function () {
    $root = storage_path('framework/testing/artwork-downloads');
    config([
        'uploads.storage_root' => $root,
        'uploads.local_originals_root' => $root,
    ]);

    if (File::exists($root)) {
        File::deleteDirectory($root);
    }

    File::makeDirectory($root, 0755, true);
});

afterEach(function () {
    $root = storage_path('framework/testing/artwork-downloads');
    if (File::exists($root)) {
        File::deleteDirectory($root);
    }
});

function makeOriginalFile(string $hash, string $ext, string $content = 'test-image-content'): string
{
    $root = rtrim((string) config('uploads.local_originals_root'), DIRECTORY_SEPARATOR);
    $firstDir = substr($hash, 0, 2);
    $secondDir = substr($hash, 2, 2);
    $dir = $root . DIRECTORY_SEPARATOR . $firstDir . DIRECTORY_SEPARATOR . $secondDir;

    File::makeDirectory($dir, 0755, true, true);

    $path = $dir . DIRECTORY_SEPARATOR . $hash . '.' . $ext;
    File::put($path, $content);

    return $path;
}

it('downloads an existing artwork file', function () {
    $hash = 'a9f3e6c1b8';
    $ext = 'png';
    makeOriginalFile($hash, $ext);

    $artwork = Artwork::factory()->create([
        'file_name' => 'Sky Sunset',
        'hash' => $hash,
        'file_ext' => $ext,
    ]);

    $response = $this->get("/download/artwork/{$artwork->id}");

    $response->assertOk();
    $response->assertDownload('Sky Sunset.png');
});

it('forces the download filename using file_name and extension', function () {
    $hash = 'b7c4d1e2f3';
    $ext = 'jpg';
    makeOriginalFile($hash, $ext);

    $artwork = Artwork::factory()->create([
        'file_name' => 'My Original Name',
        'hash' => $hash,
        'file_ext' => $ext,
    ]);

    $response = $this->get("/download/artwork/{$artwork->id}");

    $response->assertOk();
    $response->assertDownload('My Original Name.jpg');
});

it('returns 404 for a missing artwork', function () {
    $this->get('/download/artwork/999999')->assertNotFound();
});

it('returns 404 when the original file is missing', function () {
    $artwork = Artwork::factory()->create([
        'hash' => 'c1d2e3f4a5',
        'file_ext' => 'webp',
    ]);

    $this->get("/download/artwork/{$artwork->id}")->assertNotFound();
});

it('logs download metadata with user and request context', function () {
    $hash = 'd4e5f6a7b8';
    $ext = 'gif';
    makeOriginalFile($hash, $ext);

    $user = User::factory()->create();
    $artwork = Artwork::factory()->create([
        'hash' => $hash,
        'file_ext' => $ext,
    ]);

    $this->actingAs($user)
        ->withHeaders([
            'User-Agent' => 'SkinbaseTestAgent/1.0',
            'Referer' => 'https://example.test/art/' . $artwork->id,
        ])
        ->get("/download/artwork/{$artwork->id}")
        ->assertOk();

    $this->assertDatabaseHas('artwork_downloads', [
        'artwork_id' => $artwork->id,
        'user_id' => $user->id,
        'ip_address' => '127.0.0.1',
        'user_agent' => 'SkinbaseTestAgent/1.0',
        'referer' => 'https://example.test/art/' . $artwork->id,
    ]);
});

it('logs guest download with null user_id', function () {
    $hash = 'e1f2a3b4c5';
    $ext = 'png';
    makeOriginalFile($hash, $ext);

    $artwork = Artwork::factory()->create([
        'hash' => $hash,
        'file_ext' => $ext,
    ]);

    $this->get("/download/artwork/{$artwork->id}")->assertOk();

    $this->assertDatabaseHas('artwork_downloads', [
        'artwork_id' => $artwork->id,
        'user_id' => null,
    ]);
});

it('increments artwork_stats downloads on the real download route', function () {
    $hash = 'f1e2d3c4b5';
    $ext = 'png';
    makeOriginalFile($hash, $ext);

    $artwork = Artwork::factory()->create([
        'hash' => $hash,
        'file_ext' => $ext,
    ]);

    DB::table('artwork_stats')->insertOrIgnore([
        'artwork_id' => $artwork->id,
        'views' => 0,
        'views_24h' => 0,
        'views_7d' => 0,
        'downloads' => 0,
        'downloads_24h' => 0,
        'downloads_7d' => 0,
        'favorites' => 0,
        'rating_avg' => 0,
        'rating_count' => 0,
    ]);

    $this->get("/download/artwork/{$artwork->id}")->assertOk();
    $this->get("/download/artwork/{$artwork->id}")->assertOk();

    expect(DB::table('artwork_stats')->where('artwork_id', $artwork->id)->value('downloads'))->toBe(2);
    expect(DB::table('artwork_stats')->where('artwork_id', $artwork->id)->value('downloads_24h'))->toBe(2);
    expect(DB::table('artwork_stats')->where('artwork_id', $artwork->id)->value('downloads_7d'))->toBe(2);
});
