<?php
/*
namespace App\Http\Controllers;

use App\Events\InstallRequestAssigned;
use App\Events\InstallRequestCompleted;
use App\Events\InstallRequestRejected;
use App\Jobs\AssignInstallRequest;
use App\Models\InstallRequest;
use App\Models\User;
use App\Notifications\TelegramRequestAssignedNotification;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Inertia\Inertia;
use Inertia\Response;

class InstallRequestController extends Controller
{
    use AuthorizesRequests;

    public function index(Request $request): Response
    {
        $user = $request->user();

        $filters = $request->only([
            'status',
            'installer_id',
            'date_from',
            'date_to',
            'address',
            'search',
        ]);

        $requestsQuery = InstallRequest::with([
            'creator',
            'installer',
            'photos',
            'actions' => fn ($q) =>
            $q->whereIn('action', ['completed', 'rejected'])
                ->latest(),
        ])
            // 🔐 ОГРАНИЧЕНИЕ ДЛЯ МОНТАЖНИКА
            ->when(
                $user->role === 'installer',
                fn ($q) => $q->where('assigned_to', $user->id)
            )

            // 🔎 ФИЛЬТРЫ
            ->when($filters['status'] ?? null,
                fn ($q, $status) => $q->where('status', $status)
            )
            ->when($filters['installer_id'] ?? null,
                fn ($q, $id) => $q->where('assigned_to', $id)
            )
            ->when($filters['date_from'] ?? null,
                fn ($q, $date) => $q->whereDate('scheduled_date', '>=', $date)
            )
            ->when($filters['date_to'] ?? null,
                fn ($q, $date) => $q->whereDate('scheduled_date', '<=', $date)
            )*/
            /*
            ->when($filters['address'] ?? null,
                fn ($q, $address) =>
                $q->where('address', 'like', '%' . $address . '%')
            )
            ->when($filters['phone'] ?? null,
                fn ($q, $phone) =>
                $q->where('client_phone', 'like', '%' . $phone . '%')
            )*//*
            ->when($filters['search'] ?? null,
                fn ($q, $search) =>
                $q->where(function ($q) use ($search) {
                    $q->where('address', 'like', "%$search%")
                        ->orWhere('client_phone', 'like', "%$search%");
                })
            )
            ->orderByDesc('created_at');

        $requests = $requestsQuery
            ->paginate(20)
            ->withQueryString();

        // 📌 Список монтажников нужен только админу
        $installers = in_array($user->role, ['admin', 'engineer'], true)
            ? User::where('role', 'installer')
                ->orderBy('name')
                ->get(['id', 'name'])
            : [];

        return Inertia::render('requests/Index', [
            'requests'   => $requests,
            'filters'    => $filters,
            'installers' => $installers,
        ]);
    }

    public function create(Request $request): Response
    {
        $user = $request->user();

        $installers = $user->role === 'admin'
            ? User::query()->where('role', 'installer')->orderBy('name')->get(['id', 'name'])
            : [];

        return Inertia::render('requests/Create', [
            'installers' => $installers,
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'nullable|string',
            'address' => 'required|string|max:255',
            'client_name' => 'nullable|string|max:255',
            'client_phone' => 'nullable|string|max:255',
            'scheduled_date' => 'required|date',
            'region' => 'nullable|string|max:255',
            'subject' => 'nullable|string|max:255',
            'installer_id' => 'nullable|exists:users,id',
            //'photos.*' => 'image|max:10240'
            'photos.*' => 'file|mimes:jpg,jpeg,png,webp,mp4,mov,avi,webm|max:20480'
        ]);

        $installRequest = InstallRequest::create([
            ...$validated,
            'created_by' => $request->user()->id,
            'assigned_to' => $validated['installer_id'] ?? null,
            'status' => $validated['installer_id'] ? 'assigned' : 'new',
        ]);

        if ($request->hasFile('photos')) {
            foreach ($request->file('photos') as $file) {
                $path = $file->store('install-photos', 'public');
                $installRequest->photos()->create([
                    'uploaded_by' => $request->user()->id,
                    'path' => $path,
                    'type' => 'initial',
                ]);
            }
        }*/
        /*
        if (!$validated['installer_id']) {
            AssignInstallRequest::dispatch($installRequest);
        } else {
            $installRequest->actions()->create([
                'user_id' => $request->user()->id,
                'action' => 'manually-assigned',
                'comment' => 'Монтажник назначен при создании заявки',
            ]);
        }*/
/*
        return redirect()->route('requests.index')->with('success', 'Заявка создана');
    }*/

    /**
     * @throws AuthorizationException
     */
    /*
    public function edit(InstallRequest $installRequest): Response
    {
        $this->authorize('update', $installRequest);

        $installers = User::query()->where('role', 'installer')->orderBy('name')->get(['id', 'name']);

        return Inertia::render('requests/Edit', [
            'installRequest' => $installRequest->load('photos'),
            'installers' => $installers,
        ]);
    }*/

    /**
     * @throws AuthorizationException
     */
    /*
    public function update(Request $request, InstallRequest $installRequest): RedirectResponse
    {
        $this->authorize('update', $installRequest);

        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'nullable|string',
            'address' => 'required|string|max:255',
            'client_name' => 'nullable|string|max:255',
            'client_phone' => 'nullable|string|max:255',
            'scheduled_date' => 'required|date',
            'region' => 'nullable|string|max:255',
            'subject' => 'nullable|string|max:255',
            'installer_id' => 'nullable|exists:users,id',
        ]);

        $installRequest->update([
            ...$validated,
            'assigned_to' => $validated['installer_id'],
            'status' => $validated['installer_id'] ? 'assigned' : 'new',
        ]);

        return redirect()->route('requests.index')->with('success', 'Заявка обновлена');
    }
*/
    /**
     * @throws AuthorizationException
     */
    /*
    public function destroy(InstallRequest $installRequest): RedirectResponse
    {
        $this->authorize('delete', $installRequest);

        $installRequest->delete();

        return redirect()->route('requests.index')->with('success', 'Заявка удалена');
    }*/

    /**
     * @throws AuthorizationException
     */
    /*
    public function reject(InstallRequest $installRequest): RedirectResponse
    {
        $this->authorize('update', $installRequest);

        $user = auth()->user();

        $installRequest->actions()->create([
            'user_id' => $user->id,
            'action' => 'rejected',
            'comment' => 'Отказ от заявки',
        ]);

        $user->decrement('rating', 0.5);

        $installRequest->update([
            'assigned_to' => null,
            'status' => 'cancelled',
        ]);

        AssignInstallRequest::dispatch($installRequest);

        //event(new InstallRequestRejected($installRequest));

        return back()->with('success', 'Заявка отклонена');
    }

    public function complete(Request $httpRequest, InstallRequest $request): RedirectResponse
    {
        $user = $httpRequest->user();

        abort_unless($request->assigned_to === $user->id, 403);

        $validated = $httpRequest->validate([
            'note' => 'nullable|string|max:1000',
            'installation_price' => 'nullable|numeric|min:0',
            //'photos.*' => 'image|max:10240',
            'photos.*' => 'file|mimes:jpg,jpeg,png,mp4,mov,avi,webm|max:20480'
        ]);

        $request->update([
            'status' => 'done',
            'completed_at' => now(),
        ]);

        if ($httpRequest->hasFile('photos')) {
            foreach ($httpRequest->file('photos') as $file) {
                $path = $file->store('install-photos', 'public');
                $request->photos()->create([
                    'uploaded_by' => $user->id,
                    'path' => $path,
                    'type' => 'completed',
                ]);
            }
        }

        $request->actions()->create([
            'user_id' => $user->id,
            'action' => 'completed',
            'note' => $validated['note'] ?? null,
            'installation_price' => $validated['installation_price'] ?? null,
        ]);

        event(new InstallRequestCompleted($request));

        return back()->with('success', 'Заявка завершена');
    }

    public function rate(Request $request, InstallRequest $installRequest): RedirectResponse
    {
        $this->authorize('rate', $installRequest);

        $data = $request->validate([
            'rating' => 'required|numeric|min:1|max:5',
            'comment' => 'nullable|string',
        ]);

        $installer = $installRequest->installer;

        abort_if(!$installer, 400, 'Монтажник не назначен.');

        $installRequest->ratings()->create([
            'rated_user_id' => $installer->id,
            'rated_by' => $request->user()->id,
            'rating' => $data['rating'],
            'comment' => $data['comment'],
        ]);

        $installer->update([
            'rating' => $installer->ratingsReceived()->avg('rating')
        ]);

        return redirect()->route('requests.index')->with('success', 'Оценка успешно отправлена');
    }

    public function take(Request $request, InstallRequest $installRequest): RedirectResponse
    {
        abort_unless($request->user()->role === 'installer', 403);

        $installRequest->update([
            'assigned_to' => $request->user()->id,
            'status' => 'assigned',
        ]);

        event(new InstallRequestAssigned($installRequest));

        if ($request->user()->telegram_chat_id) {
            $request->user()->notify(new TelegramRequestAssignedNotification($installRequest));
        }

        return back()->with('success', 'Вы взяли заявку в работу');
    }

    public function assignInstaller(Request $request, InstallRequest $installRequest): RedirectResponse
    {
        $this->authorize('update', $installRequest);

        $validated = $request->validate([
            'installer_id' => 'required|exists:users,id',
        ]);

        $installRequest->update([
            'assigned_to' => $validated['installer_id'],
            'status' => 'assigned',
        ]);

        $installRequest->actions()->create([
            'user_id' => $request->user()->id,
            'action' => 'auto-assigned',
            'comment' => 'Монтажник назначен вручную администратором',
        ]);

        event(new InstallRequestAssigned($installRequest));

        if ($request->user()->telegram_chat_id) {
            $request->user()->notify(new TelegramRequestAssignedNotification($installRequest));
        }

        return back()->with('success', 'Монтажник назначен');
    }
}*/


namespace App\Http\Controllers;

use App\Events\InstallRequestAssigned;
use App\Events\InstallRequestCompleted;
use App\Http\Requests\StoreInstallRequest;
use App\Http\Requests\UpdateInstallRequest;
use App\Jobs\AssignInstallRequest;
use App\Models\City;
use App\Models\InstallRequest;
use App\Models\User;
use App\Notifications\TelegramRequestAssignedNotification;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use Inertia\Response;

class InstallRequestController extends Controller
{
    use AuthorizesRequests;

    public function index(Request $request): Response
    {
        $user = $request->user();

        $filters = $request->only([
            'status',
            'installer_id',
            'date_from',
            'date_to',
            'search',
        ]);

        $query = InstallRequest::query()
            ->with([
                'creator:id,name',
                'installer:id,name',
                'photos',
                'actions' => fn($q) => $q
                    ->whereIn('action', ['completed', 'rejected'])
                    ->latest(),
            ])
            ->when($user->role === 'installer', fn($q) => $q->where('assigned_to', $user->id)
            )
            ->when($filters['status'] ?? null, fn($q, $status) => $q->where('status', $status)
            )
            ->when($filters['installer_id'] ?? null, fn($q, $id) => $q->where('assigned_to', $id)
            )
            ->when($filters['date_from'] ?? null, fn($q, $date) => $q->whereDate('scheduled_date', '>=', $date)
            )
            ->when($filters['date_to'] ?? null, fn($q, $date) => $q->whereDate('scheduled_date', '<=', $date)
            )
            ->when($filters['search'] ?? null, function ($q, $search) {
                $q->where(function ($q) use ($search) {
                    $q->where('address', 'like', "%{$search}%")
                        ->orWhere('client_phone', 'like', "%{$search}%");
                });
            })
            ->latest();

        $requests = $query->paginate(20)->withQueryString();

        $installers = in_array($user->role, ['admin', 'engineer'], true)
            ? User::where('role', 'installer')
                ->orderBy('name')
                ->get(['id', 'name'])
            : [];

        return Inertia::render('requests/Index', [
            'requests' => $requests,
            'filters' => $filters,
            'installers' => $installers,
        ]);
    }

    public function create(Request $request): Response
    {
        $user = $request->user();

        $installers = $user->role === 'admin'
            ? User::where('role', 'installer')
                ->orderBy('name')
                ->get(['id', 'name'])
            : [];

        $cities = City::query()
            ->orderBy('name')
            ->get(['id', 'name']);

        return Inertia::render('requests/Create', [
            'installers' => $installers,
            'cities' => $cities,
        ]);
    }

    public function store(StoreInstallRequest $request): RedirectResponse
    {
        $validated = $request->validated();

        DB::transaction(function () use ($request, $validated) {

            $installRequest = InstallRequest::create([
                ...$validated,
                'created_by' => $request->user()->id,
                'assigned_to' => $validated['installer_id'] ?? null,
                'status' => $validated['installer_id'] ? 'assigned' : 'new',
            ]);

            $this->storePhotos(
                $installRequest,
                $request->file('photos'),
                $request->user()->id,
                'initial'
            );

            if (!$validated['installer_id']) {
                AssignInstallRequest::dispatch($installRequest);
            }
        });

        return redirect()->route('requests.index')
            ->with('success', 'Заявка создана');
    }

    /**
     * @throws AuthorizationException
     */
    public function edit(InstallRequest $installRequest): Response
    {
        $this->authorize('update', $installRequest);

        return Inertia::render('requests/Edit', [
            'installRequest' => $installRequest->load('photos'),
            'installers' => User::where('role', 'installer')
                ->orderBy('name')
                ->get(['id', 'name']),
        ]);
    }

    /**
     * @throws AuthorizationException
     */
    public function update(UpdateInstallRequest $request, InstallRequest $installRequest): RedirectResponse
    {
        $this->authorize('update', $installRequest);

        $validated = $request->validated();

        $installRequest->update([
            ...$validated,
            'assigned_to' => $validated['installer_id'] ?? null,
            'status' => $validated['installer_id'] ? 'assigned' : 'new',
        ]);

        return redirect()->route('requests.index')
            ->with('success', 'Заявка обновлена');
    }

    /**
     * @throws AuthorizationException
     */
    public function destroy(InstallRequest $installRequest): RedirectResponse
    {
        $this->authorize('delete', $installRequest);

        $installRequest->delete();

        return redirect()->route('requests.index')
            ->with('success', 'Заявка удалена');
    }

    public function take(Request $request, InstallRequest $installRequest): RedirectResponse
    {
        abort_unless($request->user()->role === 'installer', 403);

        DB::transaction(function () use ($request, $installRequest) {

            $installRequest->refresh();

            abort_if($installRequest->assigned_to !== null, 409, 'Заявка уже занята');

            $installRequest->update([
                'assigned_to' => $request->user()->id,
                'status' => 'assigned',
            ]);

            event(new InstallRequestAssigned($installRequest));

            if ($request->user()->telegram_chat_id) {
                $request->user()->notify(
                    new TelegramRequestAssignedNotification($installRequest)
                );
            }
        });

        return back()->with('success', 'Вы взяли заявку');
    }

    public function assignInstaller(Request $request, InstallRequest $installRequest): RedirectResponse
    {
        $this->authorize('update', $installRequest);

        $validated = $request->validate([
            'installer_id' => 'required|exists:users,id',
        ]);

        DB::transaction(function () use ($request, $installRequest, $validated) {

            $installer = User::findOrFail($validated['installer_id']);

            $installRequest->update([
                'assigned_to' => $installer->id,
                'status' => 'assigned',
            ]);

            $installRequest->actions()->create([
                'user_id' => $request->user()->id,
                'action' => 'assigned',
                'comment' => 'Назначено администратором',
            ]);

            event(new InstallRequestAssigned($installRequest));

            if ($installer->telegram_chat_id) {
                $installer->notify(
                    new TelegramRequestAssignedNotification($installRequest)
                );
            }
        });

        return back()->with('success', 'Монтажник назначен');
    }

    public function complete(Request $request, InstallRequest $installRequest): RedirectResponse
    {
        $user = $request->user();

        abort_unless($installRequest->assigned_to === $user->id, 403);
        abort_if($installRequest->status === 'done', 409);

        $validated = $request->validate([
            'note' => 'nullable|string|max:1000',
            'installation_price' => 'nullable|numeric|min:0',
            'photos.*' => 'file|mimes:jpg,jpeg,png,mp4,mov,avi,webm|max:20480'
        ]);

        DB::transaction(function () use ($installRequest, $request, $user, $validated) {

            $installRequest->update([
                'status' => 'done',
                'completed_at' => now(),
            ]);

            $this->storePhotos(
                $installRequest,
                $request->file('photos'),
                $user->id,
                'completed'
            );

            $installRequest->actions()->create([
                'user_id' => $user->id,
                'action' => 'completed',
                'note' => $validated['note'] ?? null,
                'installation_price' => $validated['installation_price'] ?? null,
            ]);

            event(new InstallRequestCompleted($installRequest));
        });

        return back()->with('success', 'Заявка завершена');
    }

    public function rate(Request $request, InstallRequest $installRequest): RedirectResponse
    {
        $this->authorize('rate', $installRequest);

        abort_if(
            $installRequest->ratings()
                ->where('rated_by', $request->user()->id)
                ->exists(),
            409,
            'Вы уже оценили заявку'
        );

        $data = $request->validate([
            'rating' => 'required|numeric|min:1|max:5',
            'comment' => 'nullable|string',
        ]);

        DB::transaction(function () use ($installRequest, $request, $data) {

            $installer = $installRequest->installer;

            abort_if(!$installer, 400);

            $installRequest->ratings()->create([
                'rated_user_id' => $installer->id,
                'rated_by' => $request->user()->id,
                'rating' => $data['rating'],
                'comment' => $data['comment'],
            ]);

            $installer->update([
                'rating' => $installer->ratingsReceived()->avg('rating')
            ]);
        });

        return redirect()->route('requests.index')
            ->with('success', 'Оценка отправлена');
    }

    private function storePhotos(
        InstallRequest $installRequest,
        ?array         $files,
        int            $userId,
        string         $type
    ): void
    {
        if (!$files) {
            return;
        }

        foreach ($files as $file) {
            $path = $file->store('install-photos', 'public');

            $installRequest->photos()->create([
                'uploaded_by' => $userId,
                'path' => $path,
                'type' => $type,
            ]);
        }
    }
}
