<?php

namespace Tests\Feature;

use App\Models\Company;
use App\Models\User;
use App\Support\EmployeeValidation;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Tests\TestCase;

class CompanyScopedEmailTest extends TestCase
{
    use RefreshDatabase;

    public function test_same_email_allowed_in_different_companies(): void
    {
        $a = Company::query()->create(['name' => 'Co A', 'short_name' => 'coa', 'status' => 'active']);
        $b = Company::query()->create(['name' => 'Co B', 'short_name' => 'cob', 'status' => 'active']);

        User::factory()->create([
            'email' => 'shared@example.com',
            'company_id' => $a->id,
            'password' => Hash::make('password123'),
        ]);
        User::factory()->create([
            'email' => 'shared@example.com',
            'company_id' => $b->id,
            'password' => Hash::make('password123'),
        ]);

        $this->assertSame(2, User::query()->where('email', 'shared@example.com')->count());
    }

    public function test_import_rules_reject_duplicate_email_within_company(): void
    {
        $company = Company::query()->create(['name' => 'Co A', 'short_name' => 'coa', 'status' => 'active']);
        User::factory()->create([
            'email' => 'dup@example.com',
            'company_id' => $company->id,
        ]);

        $validator = Validator::make(
            ['name' => 'X', 'email' => 'dup@example.com', 'password' => 'password123'],
            EmployeeValidation::importRules($company->id),
            EmployeeValidation::messages()
        );

        $this->assertTrue($validator->fails());
        $this->assertTrue($validator->errors()->has('email'));
    }

    public function test_tenant_login_works_with_email_and_password_only(): void
    {
        $this->withoutMiddleware();
        $company = Company::query()->create(['name' => 'Co A', 'short_name' => 'coa', 'status' => 'active']);
        User::factory()->create([
            'email' => 'tenant@example.com',
            'company_id' => $company->id,
            'password' => Hash::make('password123'),
            'allow_login' => true,
            'user_type' => User::USER_TYPE_ADMIN,
        ]);

        $this->post(route('login'), [
            'email' => 'tenant@example.com',
            'password' => 'password123',
        ])->assertRedirect();

        $this->assertAuthenticated();
    }

    public function test_api_login_works_without_company_when_email_is_unique(): void
    {
        $company = Company::query()->create(['name' => 'Co A', 'short_name' => 'coa', 'status' => 'active']);
        User::factory()->create([
            'email' => 'api@example.com',
            'company_id' => $company->id,
            'password' => Hash::make('password123'),
            'allow_login' => true,
            'user_type' => User::USER_TYPE_ADMIN,
        ]);

        $this->postJson('/api/auth/login', [
            'email' => 'api@example.com',
            'password' => 'password123',
        ])->assertOk()->assertJsonPath('user.email', 'api@example.com');
    }

    public function test_api_login_succeeds_when_only_one_duplicate_email_password_matches(): void
    {
        $a = Company::query()->create(['name' => 'Co A', 'short_name' => 'coa', 'status' => 'active']);
        $b = Company::query()->create(['name' => 'Co B', 'short_name' => 'cob', 'status' => 'active']);
        User::factory()->create([
            'email' => 'shared@example.com',
            'company_id' => $a->id,
            'password' => Hash::make('other-pass'),
            'allow_login' => true,
        ]);
        $match = User::factory()->create([
            'email' => 'shared@example.com',
            'company_id' => $b->id,
            'password' => Hash::make('password123'),
            'allow_login' => true,
        ]);

        $this->postJson('/api/auth/login', [
            'email' => 'shared@example.com',
            'password' => 'password123',
        ])->assertOk()->assertJsonPath('user.id', $match->id);
    }

    public function test_api_login_asks_to_contact_admin_when_multiple_password_matches(): void
    {
        $a = Company::query()->create(['name' => 'Co A', 'short_name' => 'coa', 'status' => 'active']);
        $b = Company::query()->create(['name' => 'Co B', 'short_name' => 'cob', 'status' => 'active']);
        User::factory()->create([
            'email' => 'shared@example.com',
            'company_id' => $a->id,
            'password' => Hash::make('password123'),
            'allow_login' => true,
        ]);
        User::factory()->create([
            'email' => 'shared@example.com',
            'company_id' => $b->id,
            'password' => Hash::make('password123'),
            'allow_login' => true,
        ]);

        $this->postJson('/api/auth/login', [
            'email' => 'shared@example.com',
            'password' => 'password123',
        ])->assertStatus(422)
            ->assertJsonValidationErrors(['email'])
            ->assertJsonFragment([
                'email' => ['Unable to Login. Please contact your administrator.'],
            ]);
    }
}
