<?php

namespace Tests\Tenant;

use App\Facades\Settings;
use App\Mail\NewReservationCustomerCopyNotification;
use Carbon\Carbon;
use Illuminate\Support\Facades\Mail;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\VehicleReservations\Jobs\ProcessIncomingReservationJob;
use Mtc\VehicleReservations\Reservation;
use Tests\TenantTestCase;

class ProcessIncomingReservationJobTest extends TenantTestCase
{
    #[\Override]
    protected function setUp(): void
    {
        parent::setUp();
        Mail::fake();
    }

    public function testTeamEmailsUseDealershipSpecificEmailsWhenConfigured()
    {
        $dealershipEmails = 'dealership-team@example.com, dealership-sales@example.com';

        $dealership = Dealership::factory()->create([
            'data' => [
                'reservation_team_emails' => $dealershipEmails,
            ],
        ]);

        // Verify dealership data is stored correctly
        $this->assertEquals($dealershipEmails, $dealership->data['reservation_team_emails']);
        $this->assertEquals(['dealership-team@example.com', 'dealership-sales@example.com'], $dealership->getReservationTeamEmails());

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id,
        ]);

        // Verify vehicle->dealership relationship works
        $this->assertEquals($dealership->id, $vehicle->dealership->id);
        $this->assertEquals(['dealership-team@example.com', 'dealership-sales@example.com'], $vehicle->dealership->getReservationTeamEmails());

        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'ingested_at' => null,
            'confirmation_sent_at' => null,
            'confirmed_at' => Carbon::now()->subMinutes(10),
        ]);

        // Verify reservation->vehicle->dealership chain works
        $this->assertEquals($dealership->id, $reservation->vehicle->dealership->id);

        new ProcessIncomingReservationJob($reservation)->handle();

        $sentMails = Mail::sent(NewReservationCustomerCopyNotification::class);
        $teamMailSent = $sentMails->contains(function (NewReservationCustomerCopyNotification $mail) {
            $recipients = collect($mail->to)->pluck('address')->toArray();
            return in_array('dealership-team@example.com', $recipients)
                && in_array('dealership-sales@example.com', $recipients);
        });

        $this->assertTrue($teamMailSent, 'Team notification should be sent to dealership-specific emails');
    }

    public function testTeamEmailsFallBackToGlobalSettingWhenDealershipHasNoEmails()
    {
        $globalEmails = 'global-team@example.com, global-sales@example.com';

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Sales',
            'group' => 'Stripe',
            'name' => 'Confirmation recipient email address(es)',
            'config_key' => 'reservations-admin-team-emails',
            'type' => 'string',
            'value' => $globalEmails,
        ]);

        $dealership = Dealership::factory()->create([
            'data' => null,
        ]);

        // Verify dealership has no reservation emails configured
        $this->assertEmpty($dealership->getReservationTeamEmails());

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id,
        ]);

        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'ingested_at' => null,
            'confirmation_sent_at' => null,
            'confirmed_at' => Carbon::now()->subMinutes(10),
        ]);

        new ProcessIncomingReservationJob($reservation)->handle();

        $sentMails = Mail::sent(NewReservationCustomerCopyNotification::class);
        $teamMailSent = $sentMails->contains(function (NewReservationCustomerCopyNotification $mail) {
            $recipients = collect($mail->to)->pluck('address')->toArray();
            return in_array('global-team@example.com', $recipients)
                && in_array('global-sales@example.com', $recipients);
        });

        $this->assertTrue($teamMailSent, 'Team notification should fall back to global emails when dealership has no emails');
    }

    public function testTeamEmailsFallBackToGlobalSettingWhenDealershipEmailsAreEmpty()
    {
        $globalEmails = 'global-fallback@example.com';

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Sales',
            'group' => 'Stripe',
            'name' => 'Confirmation recipient email address(es)',
            'config_key' => 'reservations-admin-team-emails',
            'type' => 'string',
            'value' => $globalEmails,
        ]);

        $dealership = Dealership::factory()->create([
            'data' => [
                'reservation_team_emails' => '',
            ],
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id,
        ]);

        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'ingested_at' => null,
            'confirmation_sent_at' => null,
            'confirmed_at' => Carbon::now()->subMinutes(10),
        ]);

        new ProcessIncomingReservationJob($reservation)->handle();

        $sentMails = Mail::sent(NewReservationCustomerCopyNotification::class);
        $teamMailSent = $sentMails->contains(function (NewReservationCustomerCopyNotification $mail) {
            $recipients = collect($mail->to)->pluck('address')->toArray();
            return in_array('global-fallback@example.com', $recipients);
        });

        $this->assertTrue($teamMailSent, 'Team notification should fall back to global emails when dealership emails are empty');
    }

    public function testTeamEmailsFallBackToGlobalSettingWhenVehicleHasNoDealership()
    {
        $globalEmails = 'global-nodealership@example.com';

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Sales',
            'group' => 'Stripe',
            'name' => 'Confirmation recipient email address(es)',
            'config_key' => 'reservations-admin-team-emails',
            'type' => 'string',
            'value' => $globalEmails,
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => null,
        ]);

        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'ingested_at' => null,
            'confirmation_sent_at' => null,
            'confirmed_at' => Carbon::now()->subMinutes(10),
        ]);

        new ProcessIncomingReservationJob($reservation)->handle();

        $sentMails = Mail::sent(NewReservationCustomerCopyNotification::class);
        $teamMailSent = $sentMails->contains(function (NewReservationCustomerCopyNotification $mail) {
            $recipients = collect($mail->to)->pluck('address')->toArray();
            return in_array('global-nodealership@example.com', $recipients);
        });

        $this->assertTrue($teamMailSent, 'Team notification should fall back to global emails when vehicle has no dealership');
    }

    public function testDealershipEmailsFilterOutInvalidEmails()
    {
        $dealershipEmails = 'valid@example.com, invalid-email, another-valid@example.com, not-an-email';

        $dealership = Dealership::factory()->create([
            'data' => [
                'reservation_team_emails' => $dealershipEmails,
            ],
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id,
        ]);

        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'ingested_at' => null,
            'confirmation_sent_at' => null,
            'confirmed_at' => Carbon::now()->subMinutes(10),
        ]);

        new ProcessIncomingReservationJob($reservation)->handle();

        $sentMails = Mail::sent(NewReservationCustomerCopyNotification::class);
        $teamMailSent = $sentMails->contains(function (NewReservationCustomerCopyNotification $mail) {
            $recipients = collect($mail->to)->pluck('address')->toArray();
            return in_array('valid@example.com', $recipients)
                && in_array('another-valid@example.com', $recipients)
                && !in_array('invalid-email', $recipients)
                && !in_array('not-an-email', $recipients);
        });

        $this->assertTrue($teamMailSent, 'Team notification should only be sent to valid email addresses');
    }

    public function testNoTeamEmailSentWhenNoEmailsConfigured()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Sales',
            'group' => 'Stripe',
            'name' => 'Confirmation recipient email address(es)',
            'config_key' => 'reservations-admin-team-emails',
            'type' => 'string',
            'value' => '',
        ]);

        $dealership = Dealership::factory()->create([
            'data' => [],
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id,
        ]);

        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'ingested_at' => null,
            'confirmation_sent_at' => null,
            'confirmed_at' => Carbon::now()->subMinutes(10),
            'email' => null,
        ]);

        new ProcessIncomingReservationJob($reservation)->handle();

        Mail::assertNothingSent();
    }

    public function testDealershipEmailsTakePriorityOverGlobalEmails()
    {
        $globalEmails = 'global@example.com';
        $dealershipEmails = 'dealership@example.com';

        Settings::make([
            'tab' => 'Automotive',
            'section' => 'Sales',
            'group' => 'Stripe',
            'name' => 'Confirmation recipient email address(es)',
            'config_key' => 'reservations-admin-team-emails',
            'type' => 'string',
            'value' => $globalEmails,
        ]);

        $dealership = Dealership::factory()->create([
            'data' => [
                'reservation_team_emails' => $dealershipEmails,
            ],
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id,
        ]);

        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'ingested_at' => null,
            'confirmation_sent_at' => null,
            'confirmed_at' => Carbon::now()->subMinutes(10),
        ]);

        new ProcessIncomingReservationJob($reservation)->handle();

        $sentMails = Mail::sent(NewReservationCustomerCopyNotification::class);

        // Verify dealership email was used
        $dealershipMailSent = $sentMails->contains(function (NewReservationCustomerCopyNotification $mail) {
            $recipients = collect($mail->to)->pluck('address')->toArray();
            return in_array('dealership@example.com', $recipients);
        });

        // Verify global email was NOT used
        $globalMailSent = $sentMails->contains(function (NewReservationCustomerCopyNotification $mail) {
            $recipients = collect($mail->to)->pluck('address')->toArray();
            return in_array('global@example.com', $recipients);
        });

        $this->assertTrue($dealershipMailSent, 'Dealership-specific emails should be used');
        $this->assertFalse($globalMailSent, 'Global emails should NOT be used when dealership has specific emails');
    }
}
