<?php

declare(strict_types=1);

namespace ImovelZapAi\Signatures\Presentation\Http\Controllers\Public;

use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
use ImovelZapAi\Publishing\Infrastructure\Persistence\Eloquent\TenantPublishingConfigModel;
use ImovelZapAi\Signatures\Application\Actions\RecordSignatureViewAction;
use ImovelZapAi\Signatures\Application\Actions\RejectSignatureAction;
use ImovelZapAi\Signatures\Application\Actions\RequestSignatureOtpAction;
use ImovelZapAi\Signatures\Application\Actions\SignDocumentAction;
use ImovelZapAi\Signatures\Domain\Enums\SignerStatus;
use ImovelZapAi\Signatures\Domain\Exceptions\SignatureException;
use ImovelZapAi\Tenancy\Infrastructure\Persistence\Eloquent\TenantModel;

final class PublicSignatureController extends Controller
{
    public function show(string $token, Request $request, RecordSignatureViewAction $action): View
    {
        try {
            $data = $action->execute($token, $request->ip(), $request->userAgent());
        } catch (SignatureException $e) {
            return view('signatures.public.invalid', ['message' => $e->getMessage()]);
        }

        $signatureRequest = $data['request']->load(['document.currentVersion', 'signers']);
        $signer = $data['signer'];
        $tenant = TenantModel::query()->find($signatureRequest->tenant_id);
        $branding = TenantPublishingConfigModel::query()->where('tenant_id', $signatureRequest->tenant_id)->first();

        return view('signatures.public.show', [
            'token' => $token,
            'request' => $signatureRequest,
            'signer' => $signer,
            'version' => $signatureRequest->document?->currentVersion,
            'tenantName' => $branding?->company_name ?: ($tenant?->name ?? 'Imobiliária'),
            'logoUrl' => $branding?->logo_url,
            'canSign' => in_array($signer->status, [
                SignerStatus::Pending,
                SignerStatus::Notified,
                SignerStatus::Viewed,
            ], true) && $signatureRequest->isOpen(),
        ]);
    }

    public function otp(string $token, RequestSignatureOtpAction $action): JsonResponse
    {
        try {
            $result = $action->execute($token);
        } catch (SignatureException $e) {
            return response()->json(['message' => $e->getMessage()], 422);
        }

        return response()->json($result);
    }

    public function sign(string $token, Request $request, SignDocumentAction $action): JsonResponse
    {
        $data = $request->validate([
            'typed_name' => ['required', 'string', 'max:255'],
            'otp' => ['required', 'string'],
        ]);

        try {
            $signatureRequest = $action->execute(
                $token,
                $data['typed_name'],
                $data['otp'],
                $request->ip(),
                $request->userAgent(),
            );
        } catch (SignatureException $e) {
            return response()->json(['message' => $e->getMessage()], 422);
        }

        return response()->json(['status' => $signatureRequest->status->value]);
    }

    public function reject(string $token, Request $request, RejectSignatureAction $action): JsonResponse
    {
        $data = $request->validate(['reason' => ['nullable', 'string']]);

        try {
            $signatureRequest = $action->execute($token, $data['reason'] ?? null, $request->ip());
        } catch (SignatureException $e) {
            return response()->json(['message' => $e->getMessage()], 422);
        }

        return response()->json(['status' => $signatureRequest->status->value]);
    }
}
