<?php

namespace Tests\Feature\Tenant;

use App\Models\Event;
use App\Models\Task;
use App\Models\TaskCollection;
use App\Models\Tenant;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;

class TaskApiTest extends TenantTestCase
{
    use RefreshDatabase;

    protected Tenant $tenant;

    protected User $tenantUser;

    protected string $token;

    protected function setUp(): void
    {
        parent::setUp();
        $this->mockTenantContext();
    }

    #[Test]
    public function unauthenticated_users_cannot_access_tasks()
    {
        $response = $this->getJson('/api/v1/tenant/tasks');

        $response->assertStatus(401);
    }

    #[Test]
    public function authenticated_user_can_list_tasks()
    {
        Task::factory(3)->create([
            'tenant_id' => $this->tenant->id,
            'priority' => 'medium',
        ]);

        $response = $this->authenticatedRequest('GET', '/api/v1/tenant/tasks');

        $response->assertStatus(200)
            ->assertJsonCount(3, 'data');
    }

    #[Test]
    public function tasks_are_tenant_isolated()
    {
        $otherTenant = Tenant::factory()->create();
        Task::factory(2)->create([
            'tenant_id' => $otherTenant->id,
            'priority' => 'medium',
        ]);

        Task::factory(3)->create([
            'tenant_id' => $this->tenant->id,
            'priority' => 'medium',
        ]);

        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->getJson('/api/v1/tenant/tasks');

        $response->assertStatus(200)
            ->assertJsonCount(3, 'data');
    }

    #[Test]
    public function user_can_create_task()
    {
        $taskData = [
            'title' => 'Test Task',
            'description' => 'Test description',
            'priority' => 'high',
            'due_date' => now()->addDays(7)->toISOString(),
        ];

        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->postJson('/api/v1/tenant/tasks', $taskData);

        $response->assertStatus(201)
            ->assertJson(['message' => 'Task erfolgreich erstellt.'])
            ->assertJsonPath('data.title', 'Test Task')
            ->assertJsonPath('data.tenant_id', $this->tenant->id);

        $this->assertDatabaseHas('tasks', [
            'tenant_id' => $this->tenant->id,
            'title->de' => 'Test Task',
        ]);
    }

    #[Test]
    public function task_creation_requires_valid_data()
    {
        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->postJson('/api/v1/tenant/tasks', []);

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

    #[Test]
    public function user_can_view_specific_task()
    {
        $task = Task::factory()->create([
            'tenant_id' => $this->tenant->id,
            'title' => [
                'de' => 'Viewable Task',
                'en' => 'Viewable Task',
            ],
            'priority' => 'medium',
        ]);

        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->getJson("/api/v1/tenant/tasks/{$task->id}");

        $response->assertStatus(200)
            ->assertJson(['title' => 'Viewable Task']);
    }

    #[Test]
    public function user_cannot_view_other_tenants_task()
    {
        $otherTenant = Tenant::factory()->create();
        $otherTask = Task::factory()->create([
            'tenant_id' => $otherTenant->id,
            'title' => 'Other Tenant Task',
            'priority' => 'medium',
        ]);

        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->getJson("/api/v1/tenant/tasks/{$otherTask->id}");

        $response->assertStatus(404);
    }

    #[Test]
    public function user_can_update_task()
    {
        $task = Task::factory()->create([
            'tenant_id' => $this->tenant->id,
            'title' => [
                'de' => 'Old Title',
                'en' => 'Old Title',
            ],
            'priority' => 'low',
        ]);

        $updateData = [
            'title' => 'Updated Title',
            'priority' => 'urgent',
        ];

        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->patchJson("/api/v1/tenant/tasks/{$task->id}", $updateData);

        $response->assertStatus(200)
            ->assertJson(['message' => 'Task erfolgreich aktualisiert.'])
            ->assertJsonPath('data.title', 'Updated Title')
            ->assertJsonPath('data.priority', 'urgent');

        $this->assertDatabaseHas('tasks', [
            'id' => $task->id,
            'title->de' => 'Updated Title',
            'priority' => 'urgent',
        ]);
    }

    #[Test]
    public function user_can_delete_task()
    {
        $task = Task::factory()->create([
            'tenant_id' => $this->tenant->id,
            'priority' => 'medium',
        ]);

        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->deleteJson("/api/v1/tenant/tasks/{$task->id}");

        $response->assertStatus(200)
            ->assertJson(['message' => 'Task erfolgreich gelöscht.']);

        $this->assertSoftDeleted('tasks', ['id' => $task->id]);
    }

    #[Test]
    public function user_can_assign_task_to_event()
    {
        $task = Task::factory()->create([
            'tenant_id' => $this->tenant->id,
            'priority' => 'medium',
        ]);
        $event = Event::factory()->create([
            'tenant_id' => $this->tenant->id,
        ]);

        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->postJson("/api/v1/tenant/tasks/{$task->id}/assign-event/{$event->id}");

        $response->assertStatus(200)
            ->assertJson(['message' => 'Task erfolgreich dem Event zugewiesen.']);

        $this->assertDatabaseHas('event_task', [
            'task_id' => $task->id,
            'event_id' => $event->id,
        ]);
    }

    #[Test]
    public function bulk_assign_tasks_to_event_works()
    {
        $tasks = Task::factory(3)->create([
            'tenant_id' => $this->tenant->id,
            'priority' => 'medium',
        ]);
        $event = Event::factory()->create([
            'tenant_id' => $this->tenant->id,
        ]);

        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->postJson("/api/v1/tenant/tasks/bulk-assign-event/{$event->id}", [
                'task_ids' => $tasks->pluck('id')->toArray(),
            ]);

        $response->assertStatus(200)
            ->assertJson(['message' => '3 Tasks dem Event zugewiesen.']);

        $this->assertEquals(3, $event->tasks()->count());
    }

    #[Test]
    public function can_get_tasks_for_specific_event()
    {
        $event = Event::factory()->create([
            'tenant_id' => $this->tenant->id,
        ]);
        $eventTasks = Task::factory(2)->create([
            'tenant_id' => $this->tenant->id,
            'priority' => 'medium',
        ]);
        $eventTasks->each(fn ($task) => $task->assignedEvents()->attach($event->id));

        Task::factory(3)->create([
            'tenant_id' => $this->tenant->id,
            'priority' => 'medium',
        ]); // Other tasks

        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->getJson("/api/v1/tenant/tasks/event/{$event->id}");

        $response->assertStatus(200)
            ->assertJsonCount(2, 'data');
    }

    #[Test]
    public function can_filter_tasks_by_collection()
    {
        $collection = TaskCollection::factory()->create([
            'tenant_id' => $this->tenant->id,
        ]);
        $collectionTasks = Task::factory(2)->create([
            'tenant_id' => $this->tenant->id,
            'priority' => 'medium',
        ]);
        $collectionTasks->each(function ($task) use ($collection) {
            $task->update(['collection_id' => $collection->id]);
        });

        Task::factory(3)->create([
            'tenant_id' => $this->tenant->id,
            'priority' => 'medium',
        ]); // Other tasks

        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->getJson("/api/v1/tenant/tasks?collection_id={$collection->id}");

        $response->assertStatus(200)
            ->assertJsonCount(2, 'data');
    }

    #[Test]
    public function tasks_can_be_searched()
    {
        Task::factory()->create([
            'tenant_id' => $this->tenant->id,
            'title' => ['de' => 'First Task', 'en' => 'First Task'],
            'priority' => 'medium',
        ]);
        Task::factory()->create([
            'tenant_id' => $this->tenant->id,
            'title' => ['de' => 'Search Test', 'en' => 'Search Test'],
            'priority' => 'medium',
        ]);
        Task::factory()->create([
            'tenant_id' => $this->tenant->id,
            'title' => ['de' => 'Another Task', 'en' => 'Another Task'],
            'priority' => 'medium',
        ]);

        $response = $this->withHeaders(['Authorization' => 'Bearer '.$this->token])
            ->getJson('/api/v1/tenant/tasks?search=Search');

        $response->assertStatus(200)
            ->assertJsonCount(1, 'data')
            ->assertJsonPath('data.0.title', 'Search Test');
    }
}
