<?php

namespace Tests\Feature;

use App\Models\Company;
use App\Models\Department;
use App\Models\User;
use App\Services\TenantRoleService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ProfileSettingsEmployeeTabsTest extends TestCase
{
    use RefreshDatabase;

    private function employeeUser(): User
    {
        $roles = TenantRoleService::syncAllDefaultRolesForCompany((int) Company::query()->create([
            'name' => 'Profile Tabs Co',
            'short_name' => 'PTC',
            'email' => 'profile-tabs@example.com',
            'status' => 'active',
        ])->id);

        $companyId = (int) $roles['employee']->company_id;

        return User::factory()->create([
            'company_id' => $companyId,
            'role_id' => $roles['employee']->id,
            'allow_login' => true,
            'user_type' => User::USER_TYPE_STAFF,
        ]);
    }

    public function test_profile_page_shows_basic_work_and_bank_nav_items(): void
    {
        $user = $this->employeeUser();

        $response = $this->actingAs($user)->get(route('settings.profile'));

        $response->assertOk();
        $response->assertSee('Basic Info');
        $response->assertSee('Work Info');
        $response->assertSee('Bank Account Details');
    }

    public function test_update_profile_basic_persists_allowed_fields(): void
    {
        $user = $this->employeeUser();

        $response = $this->actingAs($user)->put(route('settings.profile.basic.update'), [
            'phone' => '9876543210',
            'gender' => 'male',
            'dob' => '1990-05-15',
            'father_name' => 'John Doe Sr',
            'pan_number' => 'ABCDE1234F',
        ]);

        $response->assertRedirect(route('settings.profile') . '#basic');
        $response->assertSessionHas('success');

        $user->refresh();
        $this->assertSame('9876543210', $user->phone);
        $this->assertSame('male', $user->gender);
        $this->assertSame('1990-05-15', $user->dob?->format('Y-m-d'));
        $this->assertSame('John Doe Sr', $user->father_name);
        $this->assertSame('ABCDE1234F', $user->pan_number);
    }

    public function test_update_profile_work_persists_statutory_fields_only(): void
    {
        $user = $this->employeeUser();

        $response = $this->actingAs($user)->put(route('settings.profile.work.update'), [
            'uan_number' => '100012345678',
            'work_state' => 'Telangana',
            'pt_location' => 'Hyderabad',
        ]);

        $response->assertRedirect(route('settings.profile') . '#work');
        $response->assertSessionHas('success');

        $user->refresh();
        $this->assertSame('100012345678', $user->uan_number);
        $this->assertSame('Telangana', $user->work_state);
        $this->assertSame('Hyderabad', $user->pt_location);
    }

    public function test_update_profile_bank_persists_bank_fields(): void
    {
        $user = $this->employeeUser();

        $response = $this->actingAs($user)->put(route('settings.profile.bank.update'), [
            'account_holder_name' => 'Jane Employee',
            'bank_name' => 'HDFC Bank',
            'account_number' => '12345678901',
            'branch_name' => 'Madhapur',
            'city' => 'Hyderabad',
            'ifsc_code' => 'HDFC0001234',
        ]);

        $response->assertRedirect(route('settings.profile') . '#bank');
        $response->assertSessionHas('success');

        $user->refresh();
        $this->assertSame('Jane Employee', $user->account_holder_name);
        $this->assertSame('HDFC Bank', $user->bank_name);
        $this->assertSame('12345678901', $user->account_number);
        $this->assertSame('Madhapur', $user->branch_name);
        $this->assertSame('Hyderabad', $user->city);
        $this->assertSame('HDFC0001234', $user->ifsc_code);
    }

    public function test_hr_fields_submitted_to_work_endpoint_are_not_persisted(): void
    {
        $user = $this->employeeUser();
        $originalDepartmentId = $user->department_id;
        $originalJoiningDate = $user->joining_date;

        $otherDepartment = Department::withoutGlobalScopes()->create([
            'company_id' => $user->company_id,
            'name' => 'Engineering',
        ]);

        $this->actingAs($user)->put(route('settings.profile.work.update'), [
            'uan_number' => '100099988877',
            'work_state' => 'Karnataka',
            'pt_location' => 'Bengaluru',
            'department_id' => $otherDepartment->id,
            'joining_date' => '2020-01-01',
        ]);

        $user->refresh();
        $this->assertSame('100099988877', $user->uan_number);
        $this->assertSame('Karnataka', $user->work_state);
        $this->assertSame('Bengaluru', $user->pt_location);
        $this->assertSame($originalDepartmentId, $user->department_id);
        $this->assertEquals($originalJoiningDate?->format('Y-m-d'), $user->joining_date?->format('Y-m-d'));
    }

    public function test_hr_fields_submitted_to_basic_endpoint_are_not_persisted(): void
    {
        $user = $this->employeeUser();
        $originalEmployeeNumber = $user->employee_number;

        $this->actingAs($user)->put(route('settings.profile.basic.update'), [
            'phone' => '9123456789',
            'employee_number' => 'HACKED-001',
            'status' => 'inactive',
        ]);

        $user->refresh();
        $this->assertSame('9123456789', $user->phone);
        $this->assertSame($originalEmployeeNumber, $user->employee_number);
        $this->assertSame('active', $user->status);
    }

    public function test_cannot_overwrite_phone_when_already_set(): void
    {
        $user = $this->employeeUser();
        $user->update(['phone' => '9999999999']);

        $this->actingAs($user)->put(route('settings.profile.basic.update'), [
            'phone' => '1111111111',
        ]);

        $user->refresh();
        $this->assertSame('9999999999', $user->phone);
    }

    public function test_can_fill_empty_pan_while_phone_stays_locked(): void
    {
        $user = $this->employeeUser();
        $user->update(['phone' => '9999999999']);

        $this->actingAs($user)->put(route('settings.profile.basic.update'), [
            'phone' => '1111111111',
            'pan_number' => 'ABCDE1234F',
        ]);

        $user->refresh();
        $this->assertSame('9999999999', $user->phone);
        $this->assertSame('ABCDE1234F', $user->pan_number);
    }

    public function test_bank_account_number_locks_per_field_while_ifsc_still_updatable(): void
    {
        $user = $this->employeeUser();
        $user->update(['account_number' => '12345678901']);

        $this->actingAs($user)->put(route('settings.profile.bank.update'), [
            'account_number' => '99999999999',
            'ifsc_code' => 'HDFC0001234',
        ]);

        $user->refresh();
        $this->assertSame('12345678901', $user->account_number);
        $this->assertSame('HDFC0001234', $user->ifsc_code);
    }

    public function test_work_uan_locks_when_populated_work_state_still_updatable(): void
    {
        $user = $this->employeeUser();
        $user->update(['uan_number' => '100012345678']);

        $this->actingAs($user)->put(route('settings.profile.work.update'), [
            'uan_number' => '100099988877',
            'work_state' => 'Telangana',
        ]);

        $user->refresh();
        $this->assertSame('100012345678', $user->uan_number);
        $this->assertSame('Telangana', $user->work_state);
    }
}
