<?php

namespace App\Http\Controllers\Api\V1\Portal;

use App\Domain\Applicants\Models\Applicant;
use App\Domain\Applicants\Services\ApplicantPortalPresenter;
use App\Domain\Documents\Models\DocumentType;
use App\Domain\Documents\Services\ChecklistBuilder;
use App\Domain\Documents\Services\DocumentService;
use App\Http\Controllers\Controller;
use App\Http\Requests\Documents\UploadDocumentRequest;
use App\Support\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

/**
 * Applicant self-service portal (§26).
 *
 * Every action works on the applicant resolved from the session by
 * `portal.applicant` middleware — no endpoint here takes an applicant id.
 */
class ApplicantPortalController extends Controller
{
    public function __construct(
        private readonly ApplicantPortalPresenter $presenter,
        private readonly DocumentService $documents,
        private readonly ChecklistBuilder $checklists,
    ) {}

    public function dashboard(Request $request): JsonResponse
    {
        return ApiResponse::success($this->presenter->dashboard($this->applicant($request)));
    }

    public function application(Request $request): JsonResponse
    {
        return ApiResponse::success($this->presenter->application($this->applicant($request)));
    }

    public function status(Request $request): JsonResponse
    {
        $applicant = $this->applicant($request);

        return ApiResponse::success([
            'status' => $this->presenter->currentStatus($applicant),
            'timeline' => $this->presenter->timeline($applicant),
        ]);
    }

    public function documents(Request $request): JsonResponse
    {
        return ApiResponse::success($this->presenter->documents($this->applicant($request)));
    }

    /** Applicants upload against their own checklist only. */
    public function uploadDocument(UploadDocumentRequest $request): JsonResponse
    {
        $applicant = $this->applicant($request);

        $type = DocumentType::where('uuid', $request->string('document_type_id'))
            ->where('company_id', $applicant->company_id)
            ->firstOrFail();

        // An applicant may only upload documents that were actually requested
        // of them; anything else is not theirs to add.
        $isRequested = $this->checklists->matchingRequirements($applicant)
            ->contains(fn ($requirement) => $requirement->document_type_id === $type->getKey());

        abort_unless($isRequested, 403, 'This document has not been requested for your application.');

        $this->documents->upload($applicant, $type, $request->file('file'), $request->metadata(), $request->user());

        return ApiResponse::success(
            $this->presenter->documents($applicant->fresh()),
            "{$type->name} uploaded. It will be checked by our team.",
            status: 201,
        );
    }

    private function applicant(Request $request): Applicant
    {
        return $request->attributes->get('portal_applicant');
    }
}
