<?php

namespace App\Modules\HR\Employees\Controllers;

use App\Http\Controllers\Controller;
use App\Modules\Customization\CustomFields\DTOs\CustomFieldsPayload;
use App\Modules\Customization\CustomFields\Services\CustomFieldRendererService;
use App\Modules\Customization\CustomFields\Support\CustomFieldEntity;
use App\Modules\HR\Departments\Repositories\DepartmentRepository;
use App\Modules\HR\Employees\DTOs\EmployeeFileUploads;
use App\Modules\HR\Employees\DTOs\EmployeeWriteData;
use App\Modules\HR\Employees\Models\Employee;
use App\Modules\HR\Employees\Requests\StoreEmployeeRequest;
use App\Modules\HR\Employees\Requests\UpdateEmployeeRequest;
use App\Modules\HR\Employees\Services\EmployeeProfilePageService;
use App\Modules\HR\Employees\Services\EmployeeService;
use App\Modules\HR\Employees\Services\EmployeeUserAccountService;
use App\Modules\HR\EmploymentStatuses\Repositories\EmploymentStatusRepository;
use App\Modules\HR\EmploymentStatuses\Services\EmploymentStatusBootstrapService;
use App\Modules\HR\Positions\Repositories\PositionRepository;
use App\Modules\Platform\Geography\Repositories\GeoCountryRepository;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class EmployeePageController extends Controller
{
    public function __construct(
        private readonly EmployeeService $service,
        private readonly EmployeeProfilePageService $profile,
        private readonly DepartmentRepository $departments,
        private readonly PositionRepository $positions,
        private readonly EmploymentStatusRepository $employmentStatuses,
        private readonly EmploymentStatusBootstrapService $employmentBootstrap,
        private readonly GeoCountryRepository $countries,
        private readonly CustomFieldRendererService $customFieldRenderer,
        private readonly EmployeeUserAccountService $userAccounts,
    ) {}

    public function index(): View
    {
        return view('pages.hr.employees.index', [
            'employees' => $this->service->paginateForIndex(),
        ]);
    }

    public function show(Request $request, Employee $employee): View
    {
        $this->authorize('view', $employee);

        return view('pages.hr.employees.show', $this->profile->build(
            $employee,
            (string) $request->query('tab', 'overview'),
        ));
    }

    public function create(): View
    {
        $tenant = auth()->user()?->tenant;
        if ($tenant !== null) {
            $this->employmentBootstrap->ensureDefaults($tenant);
        }

        return view('pages.hr.employees.create', $this->formViewData($tenant, null));
    }

    public function store(StoreEmployeeRequest $request): RedirectResponse
    {
        $employee = $this->service->store(
            EmployeeWriteData::fromValidated($request->validated()),
            EmployeeFileUploads::fromRequest($request),
            CustomFieldsPayload::fromRequest($request),
        );

        return redirect()->route('hr.employees.show', $employee)
            ->with('status', __('employees.flash.created'));
    }

    public function edit(Employee $employee): View
    {
        $employee = $this->service->findForEdit($employee);
        $employee->loadMissing('tenant');
        $tenant = $employee->tenant;
        if ($tenant !== null) {
            $this->employmentBootstrap->ensureDefaults($tenant);
        }

        return view('pages.hr.employees.edit', array_merge(
            ['employee' => $employee],
            $this->formViewData($tenant, $employee),
            $tenant !== null ? $this->userAccounts->formContext($tenant, $employee) : [],
        ));
    }

    public function update(UpdateEmployeeRequest $request, Employee $employee): RedirectResponse
    {
        $updated = $this->service->update(
            $employee,
            EmployeeWriteData::fromValidated($request->validated()),
            EmployeeFileUploads::fromRequest($request),
            CustomFieldsPayload::fromRequest($request),
        );

        return redirect()->route('hr.employees.show', $updated)
            ->with('status', __('employees.flash.updated'));
    }

    public function deactivate(Employee $employee): RedirectResponse
    {
        $this->service->deactivate($employee);

        return redirect()->route('hr.employees.index')
            ->with('status', __('employees.flash.deactivated'));
    }

    /** @return array<string, mixed> */
    private function formViewData(?\App\Modules\Admin\Tenancy\Models\Tenant $tenant, ?Employee $employee): array
    {
        $tenantId = $tenant?->id;
        $defaultStatusId = $tenantId
            ? $this->employmentStatuses->findIdByLegacyCode((int) $tenantId, 'full_time')
            : null;

        return [
            'departmentOptions' => $this->departments->listForSelect(),
            'positionOptions' => $this->positions->listForSelect(),
            'employmentStatusOptions' => $tenantId ? $this->employmentStatuses->listForSelect() : [],
            'defaultEmploymentStatusId' => $defaultStatusId,
            'countryOptions' => $this->countries->listForSelect(),
            'managerOptions' => $tenantId
                ? $this->service->managerOptionsForForm((int) $tenantId, $employee)
                : [],
            'customFieldDefinitions' => $this->customFieldRenderer->definitionsFor($tenant, 'hr', 'employees'),
            'customFieldValues' => $employee
                ? $this->customFieldRenderer->valuesMapFor($tenant, CustomFieldEntity::EMPLOYEE, $employee->id)
                : [],
        ];
    }
}
