<?php

namespace Tests\Feature;

use App\Models\Company;
use App\Models\Designation;
use App\Models\Location;
use App\Models\Role;
use App\Models\Shift;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Str;
use Tests\TestCase;

class EmployeeFormValidationTest extends TestCase
{
    use RefreshDatabase;

    public function test_store_rejects_invalid_fields_for_reported_bugs(): void
    {
        $this->withoutMiddleware();
        [$actor, $ctx] = $this->createActorWithWorkContext();

        $response = $this->actingAs($actor)->from(route('employees.create'))->post(route('employees.store'), [
            'name' => 'John123',
            'email' => 'MixedCase@Demo.Local',
            'password' => 'password123',
            'phone' => '987654321',
            'father_name' => 'Father9',
            'joining_date' => '2024-06-01',
            'probation_end_date' => '2024-12-01',
            'confirmation_date' => '2024-11-01',
            'pf_join_date' => '2024-05-01',
            'pan_number' => '1234567890',
            'work_state' => 'State99',
            'pt_location' => 'Hyd@bad',
            'account_holder_name' => 'John@Doe',
            'city' => 'Hyd!',
            'designation_id' => '',
            'location_id' => '',
            'shift_id' => '',
            'report_to' => '',
        ]);

        $response->assertSessionHasErrors([
            'name',
            'phone',
            'father_name',
            'confirmation_date',
            'pf_join_date',
            'pan_number',
            'work_state',
            'pt_location',
            'account_holder_name',
            'city',
            'designation_id',
            'location_id',
            'shift_id',
            'report_to',
        ]);
        $this->assertDatabaseMissing('users', ['email' => 'mixedcase@demo.local']);
        $this->assertDatabaseMissing('users', ['email' => 'MixedCase@Demo.Local']);
    }

    public function test_store_normalizes_email_and_pan_and_accepts_valid_payload(): void
    {
        $this->withoutMiddleware();
        [$actor, $ctx] = $this->createActorWithWorkContext();

        $email = 'Valid.User+' . Str::uuid() . '@Demo.Local';
        $response = $this->actingAs($actor)->post(route('employees.store'), array_merge($ctx, [
            'name' => 'Valid User',
            'email' => $email,
            'password' => 'password123',
            'phone' => '9876543210',
            'father_name' => 'Valid Father',
            'joining_date' => '2024-06-01',
            'probation_end_date' => '2024-12-01',
            'confirmation_date' => '2024-12-02',
            'pf_join_date' => '2024-06-01',
            'pan_number' => 'abcde1234f',
            'work_state' => 'Telangana',
            'pt_location' => 'Hyderabad 1',
            'account_holder_name' => 'Valid User',
            'city' => 'Hyderabad',
        ]));

        $response->assertSessionHasNoErrors();
        $response->assertRedirect();

        $this->assertDatabaseHas('users', [
            'email' => strtolower($email),
            'pan_number' => 'ABCDE1234F',
            'phone' => '9876543210',
            'designation_id' => $ctx['designation_id'],
            'location_id' => $ctx['location_id'],
            'shift_id' => $ctx['shift_id'],
            'report_to' => $ctx['report_to'],
        ]);
    }

    public function test_update_rejects_invalid_phone_and_date_ordering(): void
    {
        $this->withoutMiddleware();
        [$actor, $ctx] = $this->createActorWithWorkContext();

        $employee = User::factory()->create([
            'company_id' => $actor->company_id,
            'user_type' => User::USER_TYPE_STAFF,
            'status' => 'active',
            'designation_id' => $ctx['designation_id'],
            'location_id' => $ctx['location_id'],
            'shift_id' => $ctx['shift_id'],
            'report_to' => $ctx['report_to'],
        ]);

        $response = $this->actingAs($actor)->from(route('employees.edit', $employee))->put(route('employees.update', $employee), array_merge($ctx, [
            'name' => $employee->name,
            'email' => $employee->email,
            'phone' => '123456789',
            'joining_date' => '2024-06-01',
            'probation_end_date' => '2024-12-01',
            'confirmation_date' => '2024-01-01',
            'pf_join_date' => '2023-01-01',
        ]));

        $response->assertSessionHasErrors(['phone', 'confirmation_date', 'pf_join_date']);
    }

    /**
     * @return array{0: User, 1: array<string, int>}
     */
    private function createActorWithWorkContext(): array
    {
        $company = Company::query()->create([
            'name' => 'Validation Co',
            'short_name' => 'VALC',
            'email' => 'validation-' . Str::uuid() . '@demo.local',
            'status' => 'active',
        ]);

        $role = Role::withoutGlobalScopes()->create([
            'company_id' => $company->id,
            'name' => 'admin',
            'display_name' => 'Admin',
        ]);

        $actor = User::factory()->create([
            'company_id' => $company->id,
            'role_id' => $role->id,
            'is_superadmin' => false,
            'user_type' => User::USER_TYPE_ADMIN,
            'status' => 'active',
        ]);

        $designation = Designation::withoutGlobalScopes()->create([
            'company_id' => $company->id,
            'name' => 'Engineer',
        ]);
        $location = Location::withoutGlobalScopes()->create([
            'company_id' => $company->id,
            'name' => 'HQ',
        ]);
        $shift = Shift::withoutGlobalScopes()->create([
            'company_id' => $company->id,
            'name' => 'General',
            'clock_in_time' => '09:00',
            'clock_out_time' => '18:00',
            'is_active' => true,
        ]);

        return [$actor, [
            'designation_id' => $designation->id,
            'location_id' => $location->id,
            'shift_id' => $shift->id,
            'report_to' => $actor->id,
            'role_id' => $role->id,
        ]];
    }
}
