<?php

namespace Tests\Feature;

use App\Models\Announcement;
use App\Models\User;
use App\Models\EmployerProfile;
use App\Models\Worker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class AnnouncementApiTest extends TestCase
{
    use RefreshDatabase;

    protected $worker;
    protected $employer;
    protected $workerToken;
    protected $employerToken;

    protected function setUp(): void
    {
        parent::setUp();

        // Create a category
        $category = \App\Models\WorkerCategory::create([
            'name' => 'General Helper',
        ]);

        // Create worker with API token
        $this->workerToken = 'worker-token-xyz';
        $this->worker = Worker::create([
            'name' => 'Jane Helper',
            'email' => 'jane@example.com',
            'phone' => '+971500000001',
            'password' => bcrypt('password'),
            'api_token' => $this->workerToken,
            'status' => 'Available',
            'nationality' => 'Indian',
            'age' => 25,
            'salary' => 1600.00,
            'availability' => 'Immediate',
            'experience' => '3 Years',
            'religion' => 'Hindu',
            'bio' => 'Experienced helper ready to work.',
            'category_id' => $category->id,
        ]);

        // Create employer with API token
        $this->employerToken = 'employer-token-abc';
        $this->employer = User::create([
            'name' => 'Employer One',
            'email' => 'emp1@example.com',
            'password' => bcrypt('password'),
            'role' => 'employer',
            'api_token' => $this->employerToken,
        ]);

        EmployerProfile::create([
            'user_id' => $this->employer->id,
            'company_name' => 'Elite Services',
            'phone' => '+971500000002',
            'country' => 'United Arab Emirates',
            'verification_status' => 'approved',
            'language' => 'English',
            'notifications' => true,
        ]);
    }

    /**
     * Test worker can retrieve all announcements.
     */
    public function test_worker_can_get_announcements()
    {
        // Create announcement
        Announcement::create([
            'title' => 'Important Update',
            'body' => 'Please keep your profile details updated.',
            'type' => 'info',
            'employer_id' => $this->employer->id,
            'status' => 'approved',
        ]);

        $response = $this->withHeaders([
            'Authorization' => 'Bearer ' . $this->workerToken,
        ])->getJson('/api/workers/announcements');

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    'announcements' => [
                        '*' => [
                            'id',
                            'title',
                            'body',
                            'type',
                            'employer_name',
                            'company_name',
                            'created_at',
                            'time_ago',
                        ]
                    ]
                ]
            ]);

        $this->assertEquals('Important Update', $response->json('data.announcements.0.title'));
        $this->assertEquals('Elite Services', $response->json('data.announcements.0.company_name'));
    }

    /**
     * Test employer can get only their posted announcements.
     */
    public function test_employer_can_get_posted_announcements()
    {
        // Announcement by this employer
        Announcement::create([
            'title' => 'Employer Ann',
            'body' => 'Employer specific message.',
            'type' => 'success',
            'employer_id' => $this->employer->id,
        ]);

        // Announcement by another employer
        $otherEmployer = User::create([
            'name' => 'Employer Two',
            'email' => 'emp2@example.com',
            'password' => bcrypt('password'),
            'role' => 'employer',
        ]);
        Announcement::create([
            'title' => 'Other Ann',
            'body' => 'Other specific message.',
            'type' => 'warning',
            'employer_id' => $otherEmployer->id,
        ]);

        $response = $this->withHeaders([
            'Authorization' => 'Bearer ' . $this->employerToken,
        ])->getJson('/api/employers/announcements');

        $response->assertStatus(200);
        $this->assertCount(1, $response->json('data.announcements'));
        $this->assertEquals('Employer Ann', $response->json('data.announcements.0.title'));
    }

    /**
     * Test employer can create a new announcement.
     */
    public function test_employer_can_create_announcement()
    {
        $response = $this->withHeaders([
            'Authorization' => 'Bearer ' . $this->employerToken,
        ])->postJson('/api/employers/announcements', [
            'title' => 'Holiday Notice',
            'body' => 'Office will be closed tomorrow.',
            'type' => 'warning'
        ]);

        $response->assertStatus(201)
            ->assertJsonStructure([
                'success',
                'message',
                'data' => [
                    'announcement' => [
                        'id',
                        'title',
                        'body',
                        'type',
                        'created_at',
                        'time_ago',
                    ]
                ]
            ]);

        $this->assertDatabaseHas('announcements', [
            'title' => 'Holiday Notice',
            'employer_id' => $this->employer->id,
            'type' => 'warning',
            'status' => 'pending',
        ]);
    }

    /**
     * Test employer can delete their own announcement.
     */
    public function test_employer_can_delete_announcement()
    {
        $announcement = Announcement::create([
            'title' => 'Delete Me',
            'body' => 'Temporary post.',
            'type' => 'info',
            'employer_id' => $this->employer->id,
        ]);

        $response = $this->withHeaders([
            'Authorization' => 'Bearer ' . $this->employerToken,
        ])->deleteJson('/api/employers/announcements/' . $announcement->id);

        $response->assertStatus(200);
        $this->assertDatabaseMissing('announcements', [
            'id' => $announcement->id,
        ]);
    }

    /**
     * Test employer cannot delete another employer's announcement.
     */
    public function test_employer_cannot_delete_other_employers_announcement()
    {
        $otherEmployer = User::create([
            'name' => 'Employer Two',
            'email' => 'emp2@example.com',
            'password' => bcrypt('password'),
            'role' => 'employer',
        ]);

        $announcement = Announcement::create([
            'title' => 'Other Post',
            'body' => 'Do not touch.',
            'type' => 'info',
            'employer_id' => $otherEmployer->id,
        ]);

        $response = $this->withHeaders([
            'Authorization' => 'Bearer ' . $this->employerToken,
        ])->deleteJson('/api/employers/announcements/' . $announcement->id);

        $response->assertStatus(404);
        $this->assertDatabaseHas('announcements', [
            'id' => $announcement->id,
        ]);
    }

    /**
     * Test worker cannot see pending announcements until approved.
     */
    public function test_worker_cannot_see_pending_announcements_until_approved()
    {
        $announcement = Announcement::create([
            'title' => 'Pending Ann',
            'body' => 'Should not be seen.',
            'type' => 'info',
            'employer_id' => $this->employer->id,
            'status' => 'pending',
        ]);

        // Worker fetches announcements
        $response = $this->withHeaders([
            'Authorization' => 'Bearer ' . $this->workerToken,
        ])->getJson('/api/workers/announcements');

        $response->assertStatus(200);
        $this->assertCount(0, $response->json('data.announcements'));

        // Admin approves it
        $announcement->update(['status' => 'approved']);

        // Worker fetches announcements again
        $response = $this->withHeaders([
            'Authorization' => 'Bearer ' . $this->workerToken,
        ])->getJson('/api/workers/announcements');

        $response->assertStatus(200);
        $this->assertCount(1, $response->json('data.announcements'));
        $this->assertEquals('Pending Ann', $response->json('data.announcements.0.title'));
    }

    /**
     * Test admin can reject announcement with remarks.
     */
    public function test_admin_can_reject_announcement_with_remarks()
    {
        $admin = User::create([
            'name' => 'Admin User',
            'email' => 'admin@example.com',
            'password' => bcrypt('password'),
            'role' => 'admin',
        ]);

        $announcement = Announcement::create([
            'title' => 'Pending Ann',
            'body' => 'Event description.',
            'type' => 'Charity',
            'employer_id' => $this->employer->id,
            'status' => 'pending',
        ]);

        $response = $this->actingAs($admin)
            ->withSession(['user' => $admin])
            ->post('/admin/announcements/' . $announcement->id . '/reject', [
                'remarks' => 'Inappropriate content or location details.',
            ]);

        $response->assertStatus(302); // redirects back
        
        $this->assertDatabaseHas('announcements', [
            'id' => $announcement->id,
            'status' => 'rejected',
            'remarks' => 'Inappropriate content or location details.',
        ]);
    }
}
