<?php

namespace Tests\Tenant;

use Mtc\MercuryDataModels\BookingDeliveryOption;
use Tests\TenantTestCase;
use Tests\UserForTenant;

class ServiceDeliveryControllerTest extends TenantTestCase
{
    use UserForTenant;

    public function testListDeliveryOptionsReturnsPaginatedResults()
    {
        BookingDeliveryOption::create(['name' => 'Drop Off', 'description' => 'Drop at dealership', 'price' => 0]);
        BookingDeliveryOption::create(['name' => 'Collection', 'description' => 'We collect', 'price' => 25.00]);
        BookingDeliveryOption::create(['name' => 'Courtesy Car', 'description' => 'Loan car provided', 'price' => 50.00]);

        $response = $this->actingAs($this->getUser())
            ->getJson('/api/service-bookings/delivery');

        $response->assertStatus(200);
        $this->assertCount(3, $response->json('data'));
        $this->assertArrayHasKey('current_page', $response->json());
    }

    public function testListDeliveryOptionsIncludesDefaultColumns()
    {
        BookingDeliveryOption::create(['name' => 'Test']);

        $response = $this->actingAs($this->getUser())
            ->getJson('/api/service-bookings/delivery');

        $response->assertStatus(200);
        $this->assertEquals(['status', 'updated'], $response->json('default_columns'));
    }

    public function testListDeliveryOptionsMapsTitle()
    {
        BookingDeliveryOption::create(['name' => 'Express Pickup']);

        $response = $this->actingAs($this->getUser())
            ->getJson('/api/service-bookings/delivery');

        $response->assertStatus(200);
        $option = $response->json('data.0');
        $this->assertEquals('Express Pickup', $option['title']);
        $this->assertNotEmpty($option['metaItems']['updated']);
        $this->assertFalse($option['disallow_delete']);
    }

    public function testCreateDeliveryOptionWithValidData()
    {
        $response = $this->actingAs($this->getUser())
            ->postJson('/api/service-bookings/delivery', [
                'name' => 'Home Delivery',
            ]);

        $response->assertStatus(201);
        $this->assertEquals(1, BookingDeliveryOption::count());

        $option = BookingDeliveryOption::first();
        $this->assertEquals('Home Delivery', $option->name);
    }

    public function testCreateDeliveryOptionRequiresName()
    {
        $response = $this->actingAs($this->getUser())
            ->postJson('/api/service-bookings/delivery', [
                'description' => 'No name provided',
                'price' => 10.00,
            ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['name']);
        $this->assertEquals(0, BookingDeliveryOption::count());
    }

    public function testShowDeliveryOptionReturnsCorrectData()
    {
        $option = BookingDeliveryOption::create([
            'name' => 'Shuttle Service',
            'description' => 'Free shuttle to dealership',
            'price' => 0,
        ]);

        $response = $this->actingAs($this->getUser())
            ->getJson('/api/service-bookings/delivery/' . $option->id);

        $response->assertStatus(200);
        $this->assertEquals('Shuttle Service', $response->json('name'));
        $this->assertEquals('Free shuttle to dealership', $response->json('description'));
        $this->assertEquals(0, $response->json('price'));
    }

    public function testUpdateDeliveryOptionWithValidData()
    {
        $option = BookingDeliveryOption::create([
            'name' => 'Original',
            'description' => 'Original desc',
            'price' => 10.00,
        ]);

        $response = $this->actingAs($this->getUser())
            ->putJson('/api/service-bookings/delivery/' . $option->id, [
                'name' => 'Updated Name',
                'description' => 'Updated description',
            ]);

        $response->assertStatus(200);
        $option->refresh();
        $this->assertEquals('Updated Name', $option->name);
        $this->assertEquals('Updated description', $option->description);
    }

    public function testUpdateDeliveryOptionRequiresName()
    {
        $option = BookingDeliveryOption::create(['name' => 'Test']);

        $response = $this->actingAs($this->getUser())
            ->putJson('/api/service-bookings/delivery/' . $option->id, [
                'description' => 'desc without name',
            ]);

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

    public function testUpdateDeliveryOptionRequiresDescriptionPresent()
    {
        $option = BookingDeliveryOption::create(['name' => 'Test']);

        $response = $this->actingAs($this->getUser())
            ->putJson('/api/service-bookings/delivery/' . $option->id, [
                'name' => 'Updated',
            ]);

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

    public function testDeleteDeliveryOptionRemovesRecord()
    {
        $option = BookingDeliveryOption::create(['name' => 'To Delete']);
        $this->assertEquals(1, BookingDeliveryOption::count());

        $response = $this->actingAs($this->getUser())
            ->deleteJson('/api/service-bookings/delivery/' . $option->id);

        $response->assertStatus(200);
        $this->assertEquals(0, BookingDeliveryOption::count());
    }

    public function testListDeliveryOptionsOrderedByLatestFirst()
    {
        $first = BookingDeliveryOption::create(['name' => 'Created First']);
        // Force a later timestamp
        BookingDeliveryOption::where('id', $first->id)->update(['created_at' => now()->subMinute()]);

        $second = BookingDeliveryOption::create(['name' => 'Created Second']);

        $response = $this->actingAs($this->getUser())
            ->getJson('/api/service-bookings/delivery');

        $response->assertStatus(200);
        $titles = collect($response->json('data'))->pluck('title')->toArray();
        $this->assertEquals('Created Second', $titles[0]);
        $this->assertEquals('Created First', $titles[1]);
    }
}
