<?php

namespace Tests\Feature;

use App\Models\Meeting;
use App\Models\MeetingType;
use App\Models\Notification;
use App\Models\Project;
use App\Models\Sprint;
use App\Models\Task;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class WorkspaceFeaturesTest extends TestCase
{
    use RefreshDatabase;

    private function authenticatedAdmin(): array
    {
        $user = User::factory()->create(['status' => 'active']);
        $this->grantAdminRole($user);

        return [$user, $user->createToken('workspace-test')->plainTextToken];
    }

    private function project(User $user): Project
    {
        return Project::create([
            'title' => 'پروژه تست Workspace',
            'project_manager_id' => $user->id,
            'created_by' => $user->id,
            'start_date' => now()->startOfMonth()->toDateString(),
            'end_date' => now()->endOfMonth()->toDateString(),
            'status' => 'in_progress',
        ]);
    }

    public function test_calendar_aggregates_real_project_sprint_task_and_meeting_events(): void
    {
        [$user, $token] = $this->authenticatedAdmin();
        $project = $this->project($user);
        $sprint = Sprint::create([
            'title' => 'Sprint تقویم',
            'project_id' => $project->id,
            'start_date' => now()->startOfWeek()->toDateString(),
            'end_date' => now()->endOfWeek()->toDateString(),
            'status' => 'active',
            'created_by' => $user->id,
        ]);
        Task::create([
            'title' => 'تسک سررسیددار',
            'project_id' => $project->id,
            'assignee_id' => $user->id,
            'reporter_id' => $user->id,
            'created_by' => $user->id,
            'due_date' => now()->toDateString(),
            'status' => 'todo',
        ]);
        Meeting::create([
            'title' => 'جلسه تقویم',
            'project_id' => $project->id,
            'sprint_id' => $sprint->id,
            'meeting_type' => 'daily_standup',
            'status' => 'scheduled',
            'date' => now()->toDateString(),
            'start_time' => '09:30',
            'created_by' => $user->id,
        ]);

        $response = $this->withToken($token)->getJson('/api/calendar/events?from='.now()->startOfMonth()->toDateString().'&to='.now()->endOfMonth()->toDateString());

        $response->assertOk()->assertJsonPath('success', true);
        $types = collect($response->json('data'))->pluck('event_type');
        $this->assertTrue($types->contains('meeting'));
        $this->assertTrue($types->contains('task'));
        $this->assertTrue($types->contains('sprint'));
        $this->assertTrue($types->contains('project'));
    }

    public function test_notification_can_be_previewed_archived_restored_and_soft_deleted(): void
    {
        [$user, $token] = $this->authenticatedAdmin();
        $notification = Notification::create([
            'user_id' => $user->id,
            'type' => 'system',
            'title' => 'اعلان تست',
            'body' => 'جزئیات اعلان',
        ]);

        $this->withToken($token)
            ->getJson("/api/notifications/{$notification->id}/preview")
            ->assertOk()
            ->assertJsonPath('data.preview.body', 'جزئیات اعلان');

        $this->withToken($token)
            ->patchJson("/api/notifications/{$notification->id}/archive")
            ->assertOk()
            ->assertJsonPath('data.archived_at', fn ($value) => filled($value));

        $this->withToken($token)
            ->patchJson("/api/notifications/{$notification->id}/restore")
            ->assertOk()
            ->assertJsonPath('data.archived_at', null);

        $this->withToken($token)->deleteJson("/api/notifications/{$notification->id}")->assertOk();
        $this->assertSoftDeleted('notifications', ['id' => $notification->id]);
    }

    public function test_sprint_creation_can_create_configured_meetings_and_workspace(): void
    {
        [$user, $token] = $this->authenticatedAdmin();
        $project = $this->project($user);
        $this->assertGreaterThan(0, MeetingType::count());

        $response = $this->withToken($token)->postJson('/api/sprints', [
            'title' => 'Sprint یکپارچه',
            'project_id' => $project->id,
            'start_date' => now()->addDay()->toDateString(),
            'end_date' => now()->addDays(14)->toDateString(),
            'member_ids' => [$user->id],
            'meeting_setup' => [[
                'type_key' => 'sprint_planning',
                'date' => now()->addDay()->toDateString(),
                'start_time' => '10:00',
            ]],
        ])->assertCreated();

        $sprintId = $response->json('data.id');
        $this->assertDatabaseHas('meetings', ['sprint_id' => $sprintId, 'meeting_type' => 'sprint_planning']);

        $this->withToken($token)
            ->getJson("/api/sprints/{$sprintId}/workspace")
            ->assertOk()
            ->assertJsonPath('data.sprint.id', $sprintId)
            ->assertJsonCount(1, 'data.meetings');
    }

    public function test_meeting_lifecycle_and_structured_outputs_are_available_in_workspace(): void
    {
        [$user, $token] = $this->authenticatedAdmin();
        $project = $this->project($user);
        $meeting = Meeting::create([
            'title' => 'جلسه چرخه عمر',
            'project_id' => $project->id,
            'meeting_type' => 'adhoc',
            'status' => 'scheduled',
            'date' => now()->toDateString(),
            'created_by' => $user->id,
        ]);

        $this->withToken($token)->postJson("/api/meetings/{$meeting->id}/start")->assertOk()->assertJsonPath('data.status', 'in_progress');
        $this->withToken($token)->postJson("/api/meetings/{$meeting->id}/decisions", ['title' => 'تصمیم قطعی'])->assertCreated();
        $this->withToken($token)->postJson("/api/meetings/{$meeting->id}/structured-action-items", [
            'title' => 'اقدام بعدی',
            'owner_id' => $user->id,
            'due_date' => now()->addDay()->toDateString(),
        ])->assertCreated();
        $this->withToken($token)->postJson("/api/meetings/{$meeting->id}/blockers", ['title' => 'مانع تست'])->assertCreated();
        $this->withToken($token)->postJson("/api/meetings/{$meeting->id}/complete", ['summary' => 'خلاصه نهایی'])->assertOk()->assertJsonPath('data.status', 'completed');

        $this->withToken($token)
            ->getJson("/api/meetings/{$meeting->id}/workspace")
            ->assertOk()
            ->assertJsonCount(1, 'data.structured_decisions')
            ->assertJsonCount(1, 'data.structured_action_items')
            ->assertJsonCount(1, 'data.blockers');
    }
}
