<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Http\Requests\Support\CloseSupportTicketRequest;
use App\Http\Requests\Support\IndexSupportTicketRequest;
use App\Http\Requests\Support\StoreSupportTicketRequest;
use App\Http\Resources\SupportTicketResource;
use App\Models\SupportTicket;
use App\Support\ApiResponse;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;

class SupportTicketController extends Controller
{
    public function index(IndexSupportTicketRequest $request)
    {
        Gate::authorize('viewAny', SupportTicket::class);

        $query = SupportTicket::query()
            ->with(['user'])
            ->withCount('replies')
            ->latest();

        $user = $request->user();

        if (! $user->hasRole('admin')) {
            $query->where('user_id', $user->id);
        }

        $this->applyFilters($query, $request, $user->hasRole('admin'));

        $perPage = min($request->integer('per_page', 15), 50);

        return SupportTicketResource::collection(
            $request->boolean('noPaginate') ? $query->get() : $query->paginate($perPage)
        );
    }

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

        try {
            DB::beginTransaction();

            $ticket = SupportTicket::create([
                ...$request->safe()->only(['category', 'title', 'body', 'attachments']),
                'user_id' => $request->user()->id,
                'status' => SupportTicket::STATUS_OPEN,
                'created_by' => $request->user()->id,
            ]);

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

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

        return ApiResponse::created(
            new SupportTicketResource($ticket->load('user')->loadCount('replies')),
            'تیکت پشتیبانی با موفقیت ثبت شد.'
        );
    }

    public function show(SupportTicket $supportTicket)
    {
        Gate::authorize('view', $supportTicket);

        $supportTicket->load([
            'user',
            'replies' => fn ($query) => $query->with('user')->oldest(),
        ])->loadCount('replies');

        return new SupportTicketResource($supportTicket);
    }

    public function close(CloseSupportTicketRequest $request, SupportTicket $supportTicket)
    {
        Gate::authorize('close', $supportTicket);

        if ($supportTicket->status === SupportTicket::STATUS_CLOSED) {
            return new SupportTicketResource(
                $supportTicket->load(['user', 'replies.user'])->loadCount('replies')
            );
        }

        $supportTicket->update([
            'status' => SupportTicket::STATUS_CLOSED,
            'closed_at' => now(),
            'close_reason' => $request->validated('close_reason'),
            'closed_by' => $request->user()->id,
        ]);

        return ApiResponse::response(
            new SupportTicketResource(
                $supportTicket->fresh()->load(['user', 'replies.user'])->loadCount('replies')
            ),
            null,
            'تیکت با موفقیت بسته شد.'
        );
    }

    private function applyFilters(Builder $query, IndexSupportTicketRequest $request, bool $isAdmin): void
    {
        if ($request->filled('category')) {
            $query->where('category', $request->input('category'));
        }

        if ($request->filled('status')) {
            $query->where('status', $request->input('status'));
        }

        if ($request->filled('date_from')) {
            $query->whereDate('created_at', '>=', $request->date('date_from'));
        }

        if ($request->filled('date_to')) {
            $query->whereDate('created_at', '<=', $request->date('date_to'));
        }

        if ($request->filled('search')) {
            $search = (string) $request->input('search');

            $query->where(function (Builder $scope) use ($search, $isAdmin): void {
                $scope->where('title', 'like', "%{$search}%")
                    ->orWhere('code', 'like', "%{$search}%")
                    ->orWhere('body', 'like', "%{$search}%");

                if ($isAdmin) {
                    $scope->orWhereHas('user', function (Builder $userQuery) use ($search): void {
                        $userQuery->where('first_name', 'like', "%{$search}%")
                            ->orWhere('last_name', 'like', "%{$search}%")
                            ->orWhere('national_code', 'like', "%{$search}%")
                            ->orWhere('cellphone', 'like', "%{$search}%")
                            ->orWhere('email', 'like', "%{$search}%");
                    });
                }
            });
        }
    }
}
