<?php

namespace Tests\Feature;

use App\Models\Booking;
use App\Models\BookingItem;
use App\Models\Category;
use App\Models\City;
use App\Models\Nationality;
use App\Models\Payment;
use App\Models\Product;
use App\Models\ServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Password;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;

class ProviderApiTest extends TestCase
{
    use RefreshDatabase;

    /**
     * @group SP-1
     * Test that a new provider is created with is_active set to false.
     *
     * @return void
     */
    public function test_new_provider_is_created_with_is_active_false()
    {
        $nationality = Nationality::factory()->create();
        $city = City::factory()->create();
        $category = Category::factory()->create();

        $providerData = [
            'name' => 'Test Provider',
            'email' => 'test@provider.com',
            'password' => 'password',
            'password_confirmation' => 'password',
            'phone' => '1234567890',
            'nationality_id' => $nationality->id,
            'id_number' => '1234567890',
            'commercial_register_type' => 'freelancer',
            'commercial_register_number' => '1234567890',
        ];

        $response = $this->postJson('/api/provider/register', $providerData);

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'data' => null,
                'message' => 'messages.registration_successful',
            ]);

        $this->assertDatabaseHas('service_providers', [
            'email' => 'test@provider.com',
            'is_active' => 0,
        ]);
    }

    /**
     * @group SP-2
     * Test that login fails for inactive providers.
     *
     * @return void
     */
    public function test_login_fails_for_inactive_provider()
    {
        $provider = ServiceProvider::factory()->create(['is_active' => 0]);

        $loginData = [
            'email' => $provider->email,
            'password' => 'password',
        ];

        $response = $this->postJson('/api/provider/login', $loginData);

        $response->assertStatus(401)
            ->assertJson([
                'success' => false,
                'message' => 'Invalid credentials.',
            ]);
    }

    /**
     * @group SP-3
     * Test the password recovery endpoint.
     *
     * @return void
     */
    public function test_password_recovery_endpoint()
    {
        $provider = ServiceProvider::factory()->create();

        $response = $this->postJson('/api/provider/password/forgot', ['email' => $provider->email]);

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'message' => 'messages.password_reset_token_sent',
            ]);
    }

    /**
     * @group SP-3
     * Test the password reset endpoint.
     *
     * @return void
     */
    public function test_password_reset_endpoint()
    {
        $provider = ServiceProvider::factory()->create();
        $this->postJson('/api/provider/password/forgot', ['email' => $provider->email]);
        $token = DB::table('password_reset_tokens')->where('email', $provider->email)->first()->token;

        $response = $this->postJson('/api/provider/password/reset', [
            'email' => $provider->email,
            'token' => $token,
            'password' => 'new-password',
            'password_confirmation' => 'new-password',
        ]);

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'message' => 'messages.password_reset_successful',
            ]);
    }

    /**
     * @group SP-11
     * Test the search and status filters for bookings.
     *
     * @return void
     */
    public function test_search_and_status_filters_for_bookings()
    {
        $provider = ServiceProvider::factory()->create();
        $booking = Booking::factory()->create(['service_provider_id' => $provider->id, 'status' => 'confirmed']);

        Sanctum::actingAs($provider, ['*']);

        $response = $this->getJson('/api/provider/bookings?status=confirmed');

        $response->assertStatus(200)
            ->assertJsonCount(1, 'data')
            ->assertJsonPath('data.0.id', $booking->id);

        $response = $this->getJson('/api/provider/bookings?search=' . $booking->id);

        $response->assertStatus(200)
            ->assertJsonCount(1, 'data')
            ->assertJsonPath('data.0.id', $booking->id);
    }

    /**
     * @group SP-15
     * Test booking cancellation status update.
     *
     * @return void
     */
    public function test_booking_cancellation_status_update()
    {
        $provider = ServiceProvider::factory()->create();
        $booking = Booking::factory()->create(['service_provider_id' => $provider->id]);

        Sanctum::actingAs($provider, ['*']);

        $response = $this->postJson('/api/provider/bookings/' . $booking->id . '/cancel');

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'message' => 'Booking cancelled successfully.',
            ]);

        $this->assertDatabaseHas('bookings', [
            'id' => $booking->id,
            'status' => 'canceled',
        ]);
    }

    /**
     * @group SP-16
     * Test dashboard analytics data.
     *
     * @return void
     */
    public function test_dashboard_analytics_data()
    {
        $provider = ServiceProvider::factory()->create();
        Booking::factory()->count(5)->create(['service_provider_id' => $provider->id]);

        Sanctum::actingAs($provider, ['*']);

        $response = $this->getJson('/api/provider/dashboard');

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    'total_clients',
                    'average_rating',
                    'recent_bookings',
                ],
                'message',
            ]);
    }

    /**
     * @group SP-17
     * Test the search and date filters for payment history.
     *
     * @return void
     */
    public function test_search_and_date_filters_for_payment_history()
    {
        $provider = ServiceProvider::factory()->create();
        $payment = Payment::factory()->create(['service_provider_id' => $provider->id, 'created_at' => now()->subMonth()]);
        Payment::factory()->create(['service_provider_id' => $provider->id, 'created_at' => now()]);

        Sanctum::actingAs($provider, ['*']);

        $response = $this->getJson('/api/provider/payments?date_filter=' . now()->subMonth()->format('Y-m'));

        $response->assertStatus(200)
            ->assertJsonCount(1, 'data')
            ->assertJsonPath('data.0.id', $payment->id);

        $response = $this->getJson('/api/provider/payments?search=' . $payment->id);

        $response->assertStatus(200)
            ->assertJsonCount(1, 'data')
            ->assertJsonPath('data.0.id', $payment->id);
    }
}
