<?php

declare(strict_types=1);

namespace ImovelZapAi\Importing\Presentation\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;
use ImovelZapAi\Importing\Application\Actions\ConfirmImportAction;
use ImovelZapAi\Importing\Application\Actions\RetryImportAction;
use ImovelZapAi\Importing\Application\Actions\UpdateImportMappingAction;
use ImovelZapAi\Importing\Application\Actions\UploadImportAction;
use ImovelZapAi\Importing\Application\Queries\GetImportDashboardQuery;
use ImovelZapAi\Importing\Application\Queries\GetImportReportQuery;
use ImovelZapAi\Importing\Domain\Exceptions\ImportException;
use ImovelZapAi\Importing\Infrastructure\Persistence\Eloquent\ImportJobModel;
use ImovelZapAi\Importing\Presentation\Http\Requests\StoreImportRequest;
use ImovelZapAi\Importing\Presentation\Http\Requests\UpdateImportMappingRequest;
use ImovelZapAi\Tenancy\Support\TenantContext;

final class ImportWizardController extends Controller
{
    public function index(GetImportDashboardQuery $dashboardQuery): View
    {
        return view('importing.dashboard', [
            'dashboard' => $dashboardQuery->execute((string) TenantContext::id()),
            'jobs' => ImportJobModel::query()->latest()->limit(20)->get(),
        ]);
    }

    public function create(): View
    {
        return view('importing.upload');
    }

    public function store(StoreImportRequest $request, UploadImportAction $action): RedirectResponse
    {
        $job = $action->execute(
            (string) TenantContext::id(),
            $request->user(),
            $request->file('file'),
            $request->validated('idempotency_key'),
        );

        return redirect()
            ->route('importing.show', $job)
            ->with('status', 'Arquivo enviado. A análise está em andamento.');
    }

    public function show(string $import): View
    {
        $job = $this->findJob($import);

        return view('importing.show', [
            'job' => $job->load(['file', 'errors']),
        ]);
    }

    public function updateMapping(
        string $import,
        UpdateImportMappingRequest $request,
        UpdateImportMappingAction $action,
    ): RedirectResponse {
        $job = $this->findJob($import);

        try {
            $action->execute($job, $request->validated());
        } catch (ImportException $e) {
            return back()->withErrors(['mapping' => $e->getMessage()]);
        }

        return back()->with('status', 'Mapeamento atualizado.');
    }

    public function confirm(string $import, ConfirmImportAction $action): RedirectResponse
    {
        $job = $this->findJob($import);

        try {
            $action->execute($job);
        } catch (ImportException $e) {
            return back()->withErrors(['confirm' => $e->getMessage()]);
        }

        return redirect()
            ->route('importing.show', $job)
            ->with('status', 'Importação enfileirada.');
    }

    public function retry(string $import, RetryImportAction $action): RedirectResponse
    {
        $job = $this->findJob($import);

        try {
            $action->execute($job);
        } catch (ImportException $e) {
            return back()->withErrors(['retry' => $e->getMessage()]);
        }

        return back()->with('status', 'Retry enfileirado.');
    }

    public function report(string $import, GetImportReportQuery $query): View
    {
        $job = $this->findJob($import);

        return view('importing.report', [
            'job' => $job,
            'report' => $query->execute($job),
        ]);
    }

    private function findJob(string $id): ImportJobModel
    {
        return ImportJobModel::query()
            ->where('tenant_id', TenantContext::id())
            ->whereKey($id)
            ->firstOrFail();
    }
}
