<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Http\Controllers\Concerns\AuthorizesProjectAccess;
use App\Http\Requests\Catalog\StoreOfferRequest;
use App\Http\Requests\Catalog\UpdateOfferRequest;
use App\Http\Resources\OfferResource;
use App\Models\Offer;
use App\Models\Project;
use App\Support\ApiResponse;
use Exception;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;

class OfferController extends Controller
{
    use AuthorizesProjectAccess;

    public function index()
    {
        Gate::authorize('viewAny', Offer::class);

        $user = Auth::user();
        $query = Offer::query()->with(['user', 'project', 'product']);

        if (! $user->hasRole('admin')) {
            $query->where(function ($builder) use ($user): void {
                $builder->where('user_id', $user->id)
                    ->orWhere('created_by', $user->id)
                    ->orWhere('offer_to', $user->id);
            });
        }

        return OfferResource::collection($query->get());
    }

    public function store(StoreOfferRequest $request)
    {
        Gate::authorize('create', Offer::class);

        if ($request->filled('project_id')) {
            $project = Project::findOrFail($request->integer('project_id'));
            $this->authorizeProjectAccess($project);
        }

        try {
            DB::beginTransaction();

            $data = $request->safe()->except(['amount']);
            $userId = Auth::id();

            $data['user_id'] = $userId;
            $data['created_by'] = $userId;
            $data['updated_by'] = $userId;
            $data['offer_date'] = now();
            $data['status'] = 'pending';
            $data['price'] = $request->input('price', $request->input('amount', 0));

            if (blank($data['name'] ?? null)) {
                $data['name'] = $request->filled('project_id')
                    ? 'درخواست خروج از پروژه #' . $request->integer('project_id')
                    : 'پیشنهاد محصول #' . $request->integer('product_id');
            }

            $offer = Offer::create($data);

            DB::commit();
        } catch (Exception $exception) {
            DB::rollBack();

            return ApiResponse::response(message: $exception->getMessage(), status: 419);
        }

        return ApiResponse::created(
            new OfferResource($offer->load(['user', 'project', 'product'])),
            'پیشنهاد با موفقیت ثبت شد.'
        );
    }

    public function show(Offer $offer)
    {
        Gate::authorize('view', $offer);

        return new OfferResource($offer->load(['user', 'project', 'product']));
    }

    public function update(UpdateOfferRequest $request, Offer $offer)
    {
        Gate::authorize('update', $offer);

        try {
            DB::beginTransaction();

            $data = $request->safe()->except(['amount']);
            $data['updated_by'] = Auth::id();

            if ($request->filled('price') || $request->filled('amount')) {
                $data['price'] = $request->input('price', $request->input('amount'));
            }

            $offer->update($data);

            DB::commit();
        } catch (Exception $exception) {
            DB::rollBack();

            return ApiResponse::response(message: $exception->getMessage(), status: 419);
        }

        return ApiResponse::success(
            new OfferResource($offer->fresh()->load(['user', 'project', 'product'])),
            'پیشنهاد با موفقیت ویرایش شد.'
        );
    }

    public function destroy(Offer $offer)
    {
        Gate::authorize('delete', $offer);

        try {
            DB::beginTransaction();
            $offer->delete();
            DB::commit();
        } catch (Exception $exception) {
            DB::rollBack();

            return ApiResponse::response(message: $exception->getMessage(), status: 419);
        }

        return ApiResponse::success(message: 'با موفقیت حذف شد');
    }
}
