<?php

namespace App\Modules\HR\Recruitment\Controllers;

use App\Http\Controllers\Controller;
use App\Modules\HR\Recruitment\DTOs\RecruitmentReportFilters;
use App\Modules\HR\Recruitment\Requests\RecruitmentReportFilterRequest;
use App\Modules\HR\Recruitment\Requests\StoreRecruitmentReportSavedFilterRequest;
use App\Modules\HR\Recruitment\Services\RecruitmentReportExcelExportService;
use App\Modules\HR\Recruitment\Services\RecruitmentReportPdfExportService;
use App\Modules\HR\Recruitment\Services\RecruitmentReportSavedFilterService;
use App\Modules\HR\Recruitment\Services\RecruitmentReportsPageService;
use App\Modules\HR\Recruitment\Support\RecruitmentReportType;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Response;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;

class RecruitmentReportsPageController extends Controller
{
    public function __construct(
        private readonly RecruitmentReportsPageService $pages,
        private readonly RecruitmentReportExcelExportService $excel,
        private readonly RecruitmentReportPdfExportService $pdf,
        private readonly RecruitmentReportSavedFilterService $savedFilters,
    ) {}

    public function index(RecruitmentReportFilterRequest $request): View
    {
        [$tenantId, $userId] = $this->tenantUser();

        return view('pages.hr.recruitment.reports.index', $this->pages->hub(
            $tenantId,
            $userId,
            RecruitmentReportFilters::fromArray($request->filters()),
        ));
    }

    public function show(RecruitmentReportFilterRequest $request, string $report): View
    {
        abort_unless(RecruitmentReportType::isValid($report), 404);
        [$tenantId, $userId] = $this->tenantUser();

        return view('pages.hr.recruitment.reports.show', $this->pages->show(
            $report,
            $tenantId,
            $userId,
            RecruitmentReportFilters::fromArray($request->filters()),
        ));
    }

    public function exportExcel(RecruitmentReportFilterRequest $request, string $report): StreamedResponse
    {
        abort_unless(RecruitmentReportType::isValid($report), 404);
        [$tenantId] = $this->tenantUser();

        return $this->excel->download(
            $report,
            $tenantId,
            RecruitmentReportFilters::fromArray($request->filters()),
        );
    }

    public function exportPdf(RecruitmentReportFilterRequest $request, string $report): Response
    {
        abort_unless(RecruitmentReportType::isValid($report), 404);
        [$tenantId] = $this->tenantUser();

        return $this->pdf->download(
            $report,
            $tenantId,
            RecruitmentReportFilters::fromArray($request->filters()),
        );
    }

    public function storeFilter(StoreRecruitmentReportSavedFilterRequest $request): RedirectResponse
    {
        [$tenantId, $userId] = $this->tenantUser();
        $data = $request->validated();
        $type = (string) $data['report_type'];
        $this->savedFilters->store(
            $tenantId,
            $userId,
            $type,
            (string) $data['name'],
            RecruitmentReportFilters::fromArray($data),
            (bool) ($data['is_default'] ?? false),
        );

        return redirect()
            ->route('hr.recruitment.reports.show', array_merge(['report' => $type], RecruitmentReportFilters::fromArray($data)->toQuery()))
            ->with('status', __('recruitment.reports.flash.filter_saved'));
    }

    public function destroyFilter(int $saved_filter): RedirectResponse
    {
        [$tenantId, $userId] = $this->tenantUser();
        $row = $this->savedFilters->findOwned($tenantId, $userId, $saved_filter);
        $type = $row->report_type;
        $this->savedFilters->destroy($tenantId, $userId, $saved_filter);

        return redirect()
            ->route('hr.recruitment.reports.show', ['report' => $type])
            ->with('status', __('recruitment.reports.flash.filter_deleted'));
    }

    public function applyFilter(int $saved_filter): RedirectResponse
    {
        [$tenantId, $userId] = $this->tenantUser();
        $row = $this->savedFilters->findOwned($tenantId, $userId, $saved_filter);

        return redirect()->route('hr.recruitment.reports.show', array_merge(
            ['report' => $row->report_type],
            is_array($row->filters) ? $row->filters : [],
        ));
    }

    /** @return array{0: int, 1: int} */
    private function tenantUser(): array
    {
        $user = auth()->user();
        abort_if($user === null || $user->tenant_id === null, 403);
        abort_unless($user->can('recruitment.reports.view'), 403);

        return [(int) $user->tenant_id, (int) $user->id];
    }
}
