<?php

namespace Tests\Unit\Models;

use Illuminate\Database\Eloquent\Model;
use App\Models\Ticket;
use App\Models\TicketResponse;
use App\Models\User;
use Carbon\Carbon;
use Tests\TestCase;

class TicketResponseTest extends TestCase
{
    public $user;
    public $ticket;
    protected function setUp(): void
    {
        parent::setUp();

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

    /** @test */
    public function it_can_create_a_ticket_response_with_factory(): void
    {
        $response = TicketResponse::factory()->create();

        $this->assertInstanceOf(TicketResponse::class, $response);
        $this->assertIsString($response->response);
    }

    /** @test */
    public function it_has_correct_fillable_attributes(): void
    {
        $responseData = [
            'ticket_id' => $this->ticket->id,
            'user_id' => $this->user->id,
            'response' => 'This is a response to the ticket.',
            'ip_address' => '192.168.1.1',
        ];

        $response = TicketResponse::query()->create($responseData);

        foreach ($responseData as $key => $value) {
            $this->assertEquals($value, $response->$key);
        }
    }

    /** @test */
    public function it_belongs_to_a_ticket(): void
    {
        $response = TicketResponse::factory()->create(['ticket_id' => $this->ticket->id]);

        $this->assertInstanceOf(Ticket::class, $response->ticket);
        $this->assertEquals($this->ticket->id, $response->ticket->id);
    }

    /** @test */
    public function it_belongs_to_a_user(): void
    {
        $response = TicketResponse::factory()->create(['user_id' => $this->user->id]);

        $this->assertInstanceOf(User::class, $response->user);
        $this->assertEquals($this->user->id, $response->user->id);
    }

    /** @test */
    public function it_casts_datetime_fields_correctly(): void
    {
        $response = TicketResponse::factory()->create([
            'created_at' => '2024-01-01 12:00:00',
            'updated_at' => '2024-01-01 12:30:00',
        ]);

        $this->assertInstanceOf(Carbon::class, $response->created_at);
        $this->assertInstanceOf(Carbon::class, $response->updated_at);
    }

    /** @test */
    public function it_orders_responses_by_creation_date(): void
    {
        $oldResponse = TicketResponse::factory()->create([
            'ticket_id' => $this->ticket->id,
            'created_at' => now()->subHours(2),
        ]);
        $newResponse = TicketResponse::factory()->create([
            'ticket_id' => $this->ticket->id,
            'created_at' => now(),
        ]);

        $responses = TicketResponse::query()->where('ticket_id', $this->ticket->id)->oldest()
            ->get();

        $this->assertEquals($oldResponse->id, $responses->first()->id);
        $this->assertEquals($newResponse->id, $responses->last()->id);
    }

    /** @test */
    public function it_can_query_responses_by_ticket(): void
    {
        TicketResponse::factory()->create([
            'ticket_id' => $this->ticket->id,
        ]);
        TicketResponse::factory()->create([
            'ticket_id' => $this->ticket->id,
        ]);

        $ticketResponses = TicketResponse::query()->where('ticket_id', $this->ticket->id)->get();

        $this->assertCount(2, $ticketResponses);
    }

    /** @test */
    public function it_handles_long_responses(): void
    {
        $longResponse = str_repeat('This is a very long response. ', 50);

        $response = TicketResponse::factory()->create(['response' => $longResponse]);

        $this->assertEquals($longResponse, $response->response);
        $this->assertGreaterThan(500, strlen((string) $response->response));
    }

    /** @test */
    public function it_uses_correct_table_name(): void
    {
        $response = new TicketResponse;

        $this->assertEquals('ticket_responses', $response->getTable());
    }

    /** @test */
    public function it_extends_model_class(): void
    {
        $response = new TicketResponse;

        $this->assertInstanceOf(Model::class, $response);
    }
}
