<?php

namespace Tests\Feature;

use App\Models\Contact;
use App\Models\Conversation;
use App\Models\Membership;
use App\Models\Organization;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class TeamManagementTest extends TestCase
{
    use RefreshDatabase;

    public function test_teams_page_lists_members_and_privileges(): void
    {
        [$owner, $organization] = $this->ownerWithOrganization();
        $agent = User::factory()->create([
            'name' => 'Support Agent',
            'email' => 'agent@example.com',
        ]);

        Membership::factory()->create([
            'organization_id' => $organization->id,
            'user_id' => $agent->id,
            'role' => 'agent',
            'privileges' => ['view_inbox', 'reply_to_customers', 'monitor_ai'],
        ]);

        $response = $this->actingAs($owner)->get(route('teams.index'));

        $response->assertOk();
        $response->assertSee('Teams');
        $response->assertSee('Support Agent');
        $response->assertSee('Monitor AI responses');
        $response->assertSee('Take over handoffs');
    }

    public function test_owner_can_create_human_team_member_with_role_and_privileges(): void
    {
        [$owner, $organization] = $this->ownerWithOrganization();

        $response = $this->actingAs($owner)->post(route('teams.store'), [
            'name' => 'Human Solver',
            'email' => 'solver@example.com',
            'password' => 'password-123',
            'role' => 'agent',
            'privileges' => ['view_inbox', 'reply_to_customers', 'take_over_handoffs', 'monitor_ai'],
        ]);

        $response->assertRedirect(route('teams.index'));

        $user = User::query()->where('email', 'solver@example.com')->firstOrFail();

        $this->assertDatabaseHas('memberships', [
            'organization_id' => $organization->id,
            'user_id' => $user->id,
            'role' => 'agent',
        ]);

        $membership = Membership::query()
            ->where('organization_id', $organization->id)
            ->where('user_id', $user->id)
            ->firstOrFail();

        $this->assertSame(['view_inbox', 'reply_to_customers', 'take_over_handoffs', 'monitor_ai'], $membership->privileges);
    }

    public function test_member_without_team_privilege_cannot_create_members(): void
    {
        [$owner, $organization] = $this->ownerWithOrganization();
        $agent = User::factory()->create();

        Membership::factory()->create([
            'organization_id' => $organization->id,
            'user_id' => $agent->id,
            'role' => 'agent',
            'privileges' => ['view_inbox', 'monitor_ai'],
        ]);

        $response = $this->actingAs($agent)->post(route('teams.store'), [
            'name' => 'Blocked User',
            'email' => 'blocked@example.com',
            'password' => 'password-123',
            'role' => 'agent',
            'privileges' => ['view_inbox'],
        ]);

        $response->assertForbidden();
        $this->assertDatabaseMissing('users', [
            'email' => 'blocked@example.com',
        ]);
    }

    public function test_privileged_member_can_assign_conversation_to_agent(): void
    {
        [$owner, $organization] = $this->ownerWithOrganization();
        $supervisor = User::factory()->create();
        $agent = User::factory()->create();

        Membership::factory()->create([
            'organization_id' => $organization->id,
            'user_id' => $supervisor->id,
            'role' => 'supervisor',
            'privileges' => ['view_inbox', 'assign_conversations', 'take_over_handoffs', 'monitor_ai'],
        ]);
        Membership::factory()->create([
            'organization_id' => $organization->id,
            'user_id' => $agent->id,
            'role' => 'agent',
            'privileges' => ['view_inbox', 'reply_to_customers', 'take_over_handoffs'],
        ]);

        $contact = Contact::factory()->create([
            'organization_id' => $organization->id,
        ]);
        $conversation = Conversation::factory()->create([
            'organization_id' => $organization->id,
            'contact_id' => $contact->id,
            'status' => 'open',
            'assigned_user_id' => null,
        ]);

        $response = $this->actingAs($supervisor)->put(route('conversations.assignment.update', $conversation), [
            'assigned_user_id' => $agent->id,
        ]);

        $response->assertRedirect();

        $conversation->refresh();
        $this->assertSame($agent->id, $conversation->assigned_user_id);
        $this->assertSame('pending_human', $conversation->status);
        $this->assertNotNull($conversation->human_takeover_at);
    }

    public function test_last_owner_cannot_be_removed(): void
    {
        [$owner, $organization, $membership] = $this->ownerWithOrganization();

        $response = $this->actingAs($owner)->delete(route('teams.destroy', $membership));

        $response->assertRedirect();
        $this->assertDatabaseHas('memberships', [
            'organization_id' => $organization->id,
            'user_id' => $owner->id,
            'role' => 'owner',
        ]);
    }

    /**
     * @return array{0: User, 1: Organization, 2: Membership}
     */
    private function ownerWithOrganization(): array
    {
        $owner = User::factory()->create();
        $organization = Organization::factory()->create();
        $membership = Membership::factory()->create([
            'organization_id' => $organization->id,
            'user_id' => $owner->id,
            'role' => 'owner',
            'privileges' => [
                'manage_team',
                'manage_channels',
                'customize_widget',
                'view_inbox',
                'reply_to_customers',
                'take_over_handoffs',
                'assign_conversations',
                'monitor_ai',
                'train_ai',
                'manage_callbacks',
                'view_reports',
            ],
        ]);

        return [$owner, $organization, $membership];
    }
}
