<?php

declare(strict_types=1);

namespace Maestro\Core\Modules\Offers\Http\Controllers;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Maestro\Core\Http\Controllers\Controller;
use Maestro\Core\Modules\Offers\Enums\OfferStatus;
use Maestro\Core\Modules\Offers\Http\Requests\PublicAcceptOfferRequest;
use Maestro\Core\Modules\Offers\Http\Requests\PublicDeclineOfferRequest;
use Maestro\Core\Modules\Offers\Http\Resources\OfferPublicResource;
use Maestro\Core\Modules\Offers\Models\Offer;
use Maestro\Core\Modules\Offers\Services\OfferSignatureStorage;

final class OfferPublicController extends Controller
{
    public function show(Request $request, string $uuid): JsonResponse
    {
        $offer = Offer::query()->where('public_uuid', $uuid)->firstOrFail();

        $offer->syncExpiryIfNeeded();
        $offer->refresh();

        if ($offer->status === OfferStatus::Sent) {
            $offer->markPublicViewed();
            $offer->refresh();
        }

        return response()->json(['data' => new OfferPublicResource($offer)]);
    }

    public function accept(PublicAcceptOfferRequest $request, string $uuid): JsonResponse
    {
        $offer = Offer::query()->where('public_uuid', $uuid)->firstOrFail();

        $offer->syncExpiryIfNeeded();
        $offer->refresh();

        abort_unless(in_array($offer->status, [OfferStatus::Sent, OfferStatus::Viewed], true), 409, 'Offer cannot be signed in its current state.');

        $path = OfferSignatureStorage::storeFromBase64Png(
            (string) $request->input('signature_png_base64'),
            (string) $offer->public_uuid
        );

        $offer->signer_name = (string) $request->input('signer_name');
        $offer->signature_path = $path;
        $offer->status = OfferStatus::Won;
        $offer->signed_at = now();
        $offer->save();

        $offer->refresh();

        return response()->json(['data' => new OfferPublicResource($offer)]);
    }

    public function decline(PublicDeclineOfferRequest $request, string $uuid): JsonResponse
    {
        $offer = Offer::query()->where('public_uuid', $uuid)->firstOrFail();

        $offer->syncExpiryIfNeeded();
        $offer->refresh();

        abort_unless(in_array($offer->status, [OfferStatus::Sent, OfferStatus::Viewed], true), 409);

        $offer->status = OfferStatus::Lost;
        $offer->decline_reason = $request->input('reason');
        $offer->declined_at = now();
        $offer->save();
        $offer->refresh();

        return response()->json(['data' => new OfferPublicResource($offer)]);
    }
}
