<?php

namespace Tests\Feature;

use App\Models\Order;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class OrderTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        Storage::fake('public');
    }

    /** @test */
    public function it_can_create_an_order()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $response = $this->postJson('/orders', [
            'name' => 'Test Order',
            'type' => Order::TYPE_STATION,
        ]);

        $response->assertStatus(201)
            ->assertJsonStructure([
                'id',
                'name',
                'type',
                'created_by',
                'created_at',
                'updated_at',
                'user',
            ]);

        $this->assertDatabaseHas('orders', [
            'name' => 'Test Order',
            'type' => Order::TYPE_STATION,
            'created_by' => $user->id,
        ]);
    }

    /** @test */
    public function it_can_upload_files_to_an_order()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $order = Order::create([
            'name' => 'Test Order',
            'type' => Order::TYPE_STATION,
            'created_by' => $user->id,
        ]);

        $file = UploadedFile::fake()->create('test.pdf', 1024);

        $response = $this->postJson("/orders/{$order->id}/files", [
            'file' => $file,
            'title' => 'Test Document',
        ]);

        $response->assertStatus(201)
            ->assertJsonStructure([
                'id',
                'title',
                'file_name',
                'mime_type',
                'size',
                'url',
            ]);

        $this->assertEquals(1, $order->fresh()->getMedia('order_files')->count());
        $this->assertEquals('Test Document', $order->fresh()->getMedia('order_files')->first()->getCustomProperty('title'));
    }

    /** @test */
    public function it_can_update_file_title()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $order = Order::create([
            'name' => 'Test Order',
            'type' => Order::TYPE_STATION,
            'created_by' => $user->id,
        ]);

        $file = UploadedFile::fake()->create('test.pdf', 1024);
        $media = $order->addOrderFile($file, 'Original Title');

        $response = $this->putJson("/orders/{$order->id}/files/{$media->id}/title", [
            'title' => 'Updated Title',
        ]);

        $response->assertStatus(200)
            ->assertJson([
                'id' => $media->id,
                'title' => 'Updated Title',
            ]);

        $this->assertEquals('Updated Title', $media->fresh()->getCustomProperty('title'));
    }

    /** @test */
    public function it_can_delete_a_file()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $order = Order::create([
            'name' => 'Test Order',
            'type' => Order::TYPE_STATION,
            'created_by' => $user->id,
        ]);

        $file = UploadedFile::fake()->create('test.pdf', 1024);
        $media = $order->addOrderFile($file, 'Test Document');

        $response = $this->deleteJson("/orders/{$order->id}/files/{$media->id}");

        $response->assertStatus(204);
        $this->assertEquals(0, $order->fresh()->getMedia('order_files')->count());
    }

    /** @test */
    public function it_validates_order_type()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $response = $this->postJson('/orders', [
            'name' => 'Test Order',
            'type' => 'invalid_type',
        ]);

        $response->assertStatus(422)
            ->assertJsonValidationErrors(['type']);
    }

    /** @test */
    public function it_requires_authentication()
    {
        $response = $this->postJson('/orders', [
            'name' => 'Test Order',
            'type' => Order::TYPE_STATION,
        ]);

        $response->assertStatus(401);
    }

    /** @test */
    public function it_can_create_station_order_with_required_files()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $order = Order::create([
            'name' => 'Station Order',
            'type' => Order::TYPE_STATION,
            'created_by' => $user->id,
        ]);

        $locationFile = UploadedFile::fake()->create('location.pdf', 1024);
        $licenseFile = UploadedFile::fake()->create('license.pdf', 1024);

        $order->addOrderFile($locationFile, 'Station Location');
        $order->addOrderFile($licenseFile, 'Station License');

        $files = $order->getMedia('order_files');
        $this->assertEquals(2, $files->count());
        $this->assertEquals('Station Location', $files->first()->getCustomProperty('title'));
        $this->assertEquals('Station License', $files->last()->getCustomProperty('title'));
    }

    /** @test */
    public function it_can_create_tanker_order_with_required_file()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $order = Order::create([
            'name' => 'Tanker Order',
            'type' => Order::TYPE_TANKER,
            'created_by' => $user->id,
        ]);

        $specsFile = UploadedFile::fake()->create('specs.pdf', 1024);
        $order->addOrderFile($specsFile, 'Tanker Specs');

        $files = $order->getMedia('order_files');
        $this->assertEquals(1, $files->count());
        $this->assertEquals('Tanker Specs', $files->first()->getCustomProperty('title'));
    }

    /** @test */
    public function it_can_create_storage_tank_order_with_no_files()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $order = Order::create([
            'name' => 'Storage Tank Order',
            'type' => Order::TYPE_DOMESTIC_STORAGE_TANK,
            'created_by' => $user->id,
        ]);

        $files = $order->getMedia('order_files');
        $this->assertEquals(0, $files->count());
    }
}
