<?php

namespace App\Modules\HR\Recruitment\Controllers;

use App\Http\Controllers\Controller;
use App\Modules\HR\Employees\Models\Employee;
use App\Modules\HR\Recruitment\Models\RecruitmentOnboardingAttachment;
use App\Modules\HR\Recruitment\Models\RecruitmentOnboardingCase;
use App\Modules\HR\Recruitment\Models\RecruitmentOnboardingTask;
use App\Modules\HR\Recruitment\Requests\StartOnboardingFromEmployeeRequest;
use App\Modules\HR\Recruitment\Requests\StoreOnboardingEmployeeDocumentRequest;
use App\Modules\HR\Recruitment\Requests\StoreOnboardingTaskAttachmentRequest;
use App\Modules\HR\Recruitment\Requests\UpdateOnboardingTaskRequest;
use App\Modules\HR\Recruitment\Services\OnboardingCaseService;
use App\Modules\HR\Recruitment\Services\OnboardingDocumentService;
use App\Modules\HR\Recruitment\Services\OnboardingTaskService;
use App\Modules\HR\Recruitment\Services\OnboardingWorkspacePageService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Illuminate\View\View;

class OnboardingWorkspaceController extends Controller
{
    public function __construct(
        private readonly OnboardingWorkspacePageService $pages,
        private readonly OnboardingCaseService $cases,
        private readonly OnboardingTaskService $tasks,
        private readonly OnboardingDocumentService $documents,
    ) {}

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

        return view('pages.hr.recruitment.onboarding.index', [
            'cases' => $this->pages->index((int) $request->user()->tenant_id, [
                'q' => $request->string('q')->toString() ?: null,
                'status' => $request->string('status')->toString() ?: null,
            ]),
            'employees' => Employee::query()
                ->where('tenant_id', $request->user()->tenant_id)
                ->where('is_active', true)
                ->orderBy('full_name')
                ->limit(300)
                ->get(['id', 'full_name', 'employee_code']),
        ]);
    }

    public function store(StartOnboardingFromEmployeeRequest $request): RedirectResponse
    {
        $this->authorize('create', RecruitmentOnboardingCase::class);
        $employee = Employee::query()
            ->where('tenant_id', $request->user()->tenant_id)
            ->whereKey((int) $request->validated('employee_id'))
            ->firstOrFail();

        $case = $this->cases->startFromEmployee($employee, (int) $request->user()->id);

        return redirect()
            ->route('hr.recruitment.onboarding.show', $case)
            ->with('status', __('recruitment.onboarding.flash.started'));
    }

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

        return view(
            'pages.hr.recruitment.onboarding.show',
            $this->pages->workspace(
                (int) $request->user()->tenant_id,
                $onboarding,
                $request->string('tab')->toString() ?: 'checklist',
            ),
        );
    }

    public function updateTask(
        UpdateOnboardingTaskRequest $request,
        RecruitmentOnboardingCase $onboarding,
        RecruitmentOnboardingTask $task,
    ): RedirectResponse {
        $this->authorize('manage', $onboarding);
        abort_unless((int) $task->onboarding_case_id === (int) $onboarding->id, 404);
        $this->tasks->update($task, $request->validated(), (int) $request->user()->id);

        return back()->with('status', __('recruitment.onboarding.flash.task_updated'));
    }

    public function storeAttachment(
        StoreOnboardingTaskAttachmentRequest $request,
        RecruitmentOnboardingCase $onboarding,
        RecruitmentOnboardingTask $task,
    ): RedirectResponse {
        $this->authorize('manage', $onboarding);
        abort_unless((int) $task->onboarding_case_id === (int) $onboarding->id, 404);
        $this->tasks->attach($task, $request->file('attachment'), (int) $request->user()->id);

        return back()->with('status', __('recruitment.onboarding.flash.attachment_added'));
    }

    public function downloadAttachment(
        RecruitmentOnboardingCase $onboarding,
        RecruitmentOnboardingAttachment $attachment,
    ): StreamedResponse {
        $this->authorize('view', $onboarding);
        $attachment->loadMissing('task');
        abort_unless((int) $attachment->task?->onboarding_case_id === (int) $onboarding->id, 404);

        return Storage::disk($attachment->disk)->download($attachment->path, $attachment->original_name);
    }

    public function storeDocument(
        StoreOnboardingEmployeeDocumentRequest $request,
        RecruitmentOnboardingCase $onboarding,
    ): RedirectResponse {
        $this->authorize('manage', $onboarding);
        $this->documents->upload(
            $onboarding->load('tasks'),
            (string) $request->validated('type'),
            $request->file('document'),
            (int) $request->user()->id,
            $request->validated('expires_at'),
        );

        return back()->with('status', __('recruitment.onboarding.flash.document_uploaded'));
    }
}
