<?php

namespace Tests\Unit;

use App\Services\VirtualTryonImageService;
use App\User;
use App\UserFacePhoto;
use App\VirtualTryonResult;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\RefreshDatabaseWithoutSeeds;
use Tests\TestCase;

class VirtualTryonImageServiceTest extends TestCase
{
    use RefreshDatabaseWithoutSeeds;

    protected $service;
    protected $user;

    protected function setUp(): void
    {
        parent::setUp();
        $this->service = new VirtualTryonImageService();
        Storage::fake('tryon_local');

        $this->user = factory(User::class)->create();
    }

    public function test_upload_face_photo_success()
    {
        if (!extension_loaded('gd')) {
            $this->markTestSkipped('GD extension required');
        }

        // ->image() generates a real GD-encoded file so getimagesize() + Intervention succeed.
        $file = UploadedFile::fake()->image('face.jpg', 400, 400);

        $photo = $this->service->uploadFacePhoto($file, $this->user->id);

        $this->assertInstanceOf(UserFacePhoto::class, $photo);
        $this->assertEquals($this->user->id, $photo->user_id);
        $this->assertTrue($photo->is_default); // First photo is default
        Storage::disk('tryon_local')->assertExists($photo->storage_path);
    }

    public function test_upload_face_photo_stores_portrait_canvas()
    {
        if (!extension_loaded('gd')) {
            $this->markTestSkipped('GD extension required');
        }

        $file = UploadedFile::fake()->image('landscape.jpg', 900, 500);

        $photo = $this->service->uploadFacePhoto($file, $this->user->id);
        $imageData = Storage::disk('tryon_local')->get($photo->storage_path);
        $info = getimagesizefromstring($imageData);

        $this->assertEquals(512, $info[0]);
        $this->assertEquals(682, $info[1]);
    }

    public function test_upload_rejects_when_3_photos_exist()
    {
        for ($i = 0; $i < 3; $i++) {
            UserFacePhoto::create([
                'user_id' => $this->user->id,
                'file_path' => 'https://cdn.example.com/face-' . $i . '.jpg',
                'storage_path' => 'face-photos/' . $this->user->id . '/face-' . $i . '.jpg',
                'is_default' => $i === 0,
            ]);
        }

        $file = UploadedFile::fake()->create('face4.jpg', 100, 'image/jpeg');

        $this->expectException(\Exception::class);
        $this->expectExceptionMessage('最大3枚');

        $this->service->uploadFacePhoto($file, $this->user->id);
    }

    public function test_delete_face_photo_removes_from_db_and_storage()
    {
        $storagePath = 'face-photos/' . $this->user->id . '/to-delete.jpg';
        Storage::disk('tryon_local')->put($storagePath, 'fake image data');

        $photo = UserFacePhoto::create([
            'user_id' => $this->user->id,
            'file_path' => 'https://cdn.example.com/to-delete.jpg',
            'storage_path' => $storagePath,
            'is_default' => true,
        ]);

        $this->service->deleteFacePhoto($photo);

        $this->assertDatabaseMissing('user_face_photos', ['id' => $photo->id]);
        Storage::disk('tryon_local')->assertMissing($storagePath);
    }

    public function test_download_with_watermark_returns_response()
    {
        if (!extension_loaded('gd')) {
            $this->markTestSkipped('GD extension required');
        }

        $product = \App\Product::create([
            'name' => 'Watermark Test',
            'code' => 'WM-TEST',
            'slug' => 'watermark-test',
            'image' => 'wm-test.jpg',
            'type' => 1,
            'status' => 1,
            'is_activated' => 1,
            'is_deleted' => 0,
        ]);

        // `code` and `user_id` are excluded from $fillable; assign directly.
        $result = new VirtualTryonResult();
        $result->code = 'watermark-test-code';
        $result->user_id = $this->user->id;
        $result->fill([
            'product_id' => $product->id,
            'source_image' => 'wm-test.jpg',
            'result_image' => 'virtual-tryon/results/watermark-test-code.jpg',
            'status' => 'completed',
            'expires_at' => now()->addDays(90),
        ]);
        $result->save();

        // Generate a real small JPEG so Intervention can decode it.
        $img = imagecreatetruecolor(100, 100);
        imagefilledrectangle($img, 0, 0, 100, 100, imagecolorallocate($img, 200, 200, 200));
        ob_start();
        imagejpeg($img, null, 85);
        $imageData = ob_get_clean();
        imagedestroy($img);

        Storage::disk('tryon_local')->put($result->result_image, $imageData);

        $response = $this->service->downloadWithWatermark($result);

        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('image/jpeg', $response->headers->get('Content-Type'));
        $this->assertStringContainsString('kirei_tryon_', $response->headers->get('Content-Disposition'));
    }
}
