<?php

namespace App\Modules\HR\Contracts\Controllers;

use App\Http\Controllers\Controller;
use App\Modules\HR\Contracts\DTOs\ContractWriteData;
use App\Modules\HR\Contracts\Models\EmploymentContract;
use App\Modules\HR\Contracts\Repositories\ContractTemplateRepository;
use App\Modules\HR\Contracts\Repositories\EmploymentContractRepository;
use App\Modules\HR\Contracts\Requests\StoreEmploymentContractRequest;
use App\Modules\HR\Contracts\Requests\TerminateContractRequest;
use App\Modules\HR\Contracts\Requests\UpdateEmploymentContractRequest;
use App\Modules\HR\Contracts\Services\EmploymentContractService;
use App\Modules\HR\Contracts\Support\ContractType;
use App\Modules\HR\Employees\Models\Employee;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class EmploymentContractsPageController extends Controller
{
    public function __construct(
        private readonly EmploymentContractService $service,
        private readonly EmploymentContractRepository $repository,
        private readonly ContractTemplateRepository $templates,
    ) {}

    public function index(Request $request): View
    {
        $this->authorize('viewAny', EmploymentContract::class);

        return view('pages.hr.contracts.index', [
            'contracts' => $this->repository->paginateForIndex((int) $this->tenantId(), $request),
        ]);
    }

    public function create(): View
    {
        $this->authorize('create', EmploymentContract::class);

        return view('pages.hr.contracts.create', $this->formShared());
    }

    public function store(StoreEmploymentContractRequest $request): RedirectResponse
    {
        $this->service->store(
            ContractWriteData::fromValidated($request->validated()),
            $request->file('attachment'),
            (int) $request->user()->id,
        );

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

    public function edit(EmploymentContract $employmentContract): View
    {
        $this->authorize('update', $employmentContract);

        return view('pages.hr.contracts.edit', array_merge($this->formShared(), [
            'contract' => $employmentContract,
        ]));
    }

    public function update(UpdateEmploymentContractRequest $request, EmploymentContract $employmentContract): RedirectResponse
    {
        $this->service->update(
            $employmentContract,
            ContractWriteData::fromValidated($request->validated()),
            $request->file('attachment'),
        );

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

    public function deactivate(EmploymentContract $employmentContract): RedirectResponse
    {
        $this->authorize('deactivate', $employmentContract);
        $this->service->deactivate($employmentContract);

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

    public function amend(EmploymentContract $employmentContract): RedirectResponse
    {
        $this->authorize('update', $employmentContract);
        $copy = $this->service->createAmendment($employmentContract, (int) auth()->id());

        return redirect()->route('hr.contracts.edit', $copy)->with('status', __('contracts.flash.amended'));
    }

    public function renew(EmploymentContract $employmentContract): RedirectResponse
    {
        $this->authorize('update', $employmentContract);
        $copy = $this->service->renew($employmentContract, (int) auth()->id());

        return redirect()->route('hr.contracts.edit', $copy)->with('status', __('contracts.flash.renewed'));
    }

    public function terminate(
        TerminateContractRequest $request,
        EmploymentContract $employmentContract,
    ): RedirectResponse {
        $this->service->terminate($employmentContract, $request->validated('termination_reason'));

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

    /**
     * @return array<string, mixed>
     */
    private function formShared(): array
    {
        $types = [];
        foreach (ContractType::all() as $type) {
            $types[$type] = __('contracts.types.'.$type);
        }

        return [
            'employees' => Employee::query()->where('tenant_id', $this->tenantId())->orderBy('full_name')->get(),
            'types' => $types,
            'templates' => $this->templates->active($this->tenantId()),
        ];
    }

    private function tenantId(): int
    {
        $id = auth()->user()?->tenant_id;
        abort_if($id === null, 403);

        return (int) $id;
    }
}
