<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\BorrowRequest;
use App\Models\RoomBooking;
use App\Models\VehicleBooking;
use App\Models\Item;
use App\Models\ItemRequest;
use App\Models\RequestItem;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class VerificationController extends Controller
{
    public function index()
    {
        $user = Auth::user();

        // 1. Query peminjaman barang
        $borrowQuery = BorrowRequest::with(['user', 'item', 'histories.user'])
            ->orderBy('created_at', 'desc');

        switch ($user->role) {
            case 'staff_bidang':
            case 'sekretariat':
                $borrowQuery->where('status', 'pending');
                break;
            case 'kepala_bidang':
                $borrowQuery->whereIn('status', ['staff_approved', 'sekretariat_approved']);
                break;
            default:
                $borrowQuery->where('id', -1);
                break;
        }

        $borrowRequests = $borrowQuery->get();

        // 2. Query ruangan
        $roomRequests = collect();
        if (in_array($user->role, ['staff_bidang', 'sekretariat'], true)) {
            $roomRequests = RoomBooking::with(['user', 'room'])
                ->where('status', 'pending')
                ->orderBy('created_at', 'desc')
                ->get();
        } elseif ($user->role === 'kepala_bidang') {
            $roomRequests = RoomBooking::with(['user', 'room'])
                ->whereIn('status', ['staff_approved', 'sekretariat_approved'])
                ->orderBy('created_at', 'desc')
                ->get();
        }

        // 3. Query kendaraan
        $vehicleRequests = collect();
        if (in_array($user->role, ['staff_bidang', 'sekretariat'], true)) {
            $vehicleRequests = VehicleBooking::with(['user', 'vehicle'])
                ->where('status', 'pending')
                ->orderBy('created_at', 'desc')
                ->get();
        } elseif ($user->role === 'kepala_bidang') {
            $vehicleRequests = VehicleBooking::with(['user', 'vehicle'])
                ->whereIn('status', ['staff_approved', 'sekretariat_approved'])
                ->orderBy('created_at', 'desc')
                ->get();
        }

        // 4. Query pengembalian barang
        $returnRequests = collect();
        if ($user->role === 'sekretariat') {
            $returnRequests = BorrowRequest::with(['user', 'item'])
                ->where('status', 'return_pending')
                ->orderBy('updated_at', 'desc')
                ->get();
        }

        // 5. Query permintaan barang habis pakai
        $itemRequests = collect();
        $itemRequestQuery = ItemRequest::with(['user', 'item', 'approver'])
            ->orderBy('created_at', 'desc');

        switch ($user->role) {
            case 'staff_bidang':
                $itemRequests = $itemRequestQuery->where('status', 'pending')->get();
                break;
            case 'kepala_bidang':
                $itemRequests = $itemRequestQuery->where('status', 'staff_approved')->get();
                break;
        }

        // 6. Kasih type
        $borrowRequests->each(function ($item) {
            $item->type = 'borrow';
        });

        $roomRequests->each(function ($item) {
            $item->type = 'room';
        });

        $vehicleRequests->each(function ($item) {
            $item->type = 'vehicle';
        });

        $returnRequests->each(function ($item) {
            $item->type = 'return';
        });

        $itemRequests->each(function ($item) {
            $item->type = 'item_request';
        });

        // 7. Gabung semua
        $requests = $borrowRequests
            ->concat($roomRequests)
            ->concat($vehicleRequests)
            ->concat($returnRequests)
            ->concat($itemRequests)
            ->sortByDesc(function ($item) {
                return $item->updated_at ?? $item->created_at;
            });

        $workflowSteps = [
            ['id' => 'user', 'title' => 'User Request', 'role' => 'user'],
            ['id' => 'staff', 'title' => 'Review Staff', 'role' => 'staff_bidang'],
            ['id' => 'kepala', 'title' => 'Approval Kepala', 'role' => 'kepala_bidang'],
            ['id' => 'sekretariat', 'title' => 'Final/Return', 'role' => 'sekretariat']
        ];

        return view('verification.index', compact('requests', 'workflowSteps'));
    }

    public function processAction(Request $request, $id)
    {
        $request->validate([
            'action' => 'required|in:approve,reject,revise,cancel',
            'comment' => in_array($request->action, ['reject', 'revise']) ? 'required|string|max:500' : 'nullable|string|max:500',
            'final_condition' => 'nullable|in:baik,rusak_ringan,rusak_berat'
        ]);

        $type = $request->query('type', 'borrow');

        if ($type === 'room') {
            return $this->processRoomAction($request, $id);
        } elseif ($type === 'vehicle') {
            return $this->processVehicleAction($request, $id);
        } elseif ($type === 'return') {
            return $this->processReturnAction($request, $id);
        } elseif ($type === 'item_request') {
            if (!in_array(Auth::user()->role, ['staff_bidang', 'kepala_bidang'], true)) {
                abort(403);
            }

            return $this->processItemRequestAction($request, $id);
        } else {
            return $this->processBorrowAction($request, $id);
        }
    }

    public function approve(Request $request, $id)
    {
        $request->merge([
            'action' => 'approve',
            'comment' => $request->input('comment'),
        ]);

        return $this->processBorrowAction($request, $id);
    }

    public function reject(Request $request, $id)
    {
        $request->merge([
            'action' => 'reject',
        ]);

        return $this->processBorrowAction($request, $id);
    }

    public function requestRevision(Request $request, $id)
    {
        $request->merge([
            'action' => 'revise',
        ]);

        return $this->processBorrowAction($request, $id);
    }

    public function processVehicleAction(Request $request, $id)
    {
        $user = Auth::user();
        $vehicleBooking = VehicleBooking::findOrFail($id);
        $action = $request->input('action');

        if (!in_array($user->role, ['staff_bidang', 'kepala_bidang', 'sekretariat'], true)) {
            return back()->with('error', 'Anda tidak berwenang memproses permohonan kendaraan.');
        }

        if ($action === 'approve') {
            if ($vehicleBooking->status === 'pending' && $user->role === 'staff_bidang') {
                $vehicleBooking->status = 'staff_approved';
            } elseif ($vehicleBooking->status === 'pending' && $user->role === 'sekretariat') {
                $vehicleBooking->status = 'sekretariat_approved';
            } elseif (in_array($vehicleBooking->status, ['staff_approved', 'sekretariat_approved'], true) && $user->role === 'kepala_bidang') {
                $vehicleBooking->status = 'final_approved';
            } else {
                return back()->with('error', 'Status permohonan kendaraan belum sesuai tahap verifikasi.');
            }

            $msg = 'Peminjaman kendaraan disetujui.';
        } elseif ($action === 'reject') {
            if (!(
                $vehicleBooking->status === 'pending' && in_array($user->role, ['staff_bidang', 'sekretariat'], true)
                || in_array($vehicleBooking->status, ['staff_approved', 'sekretariat_approved'], true) && $user->role === 'kepala_bidang'
            )) {
                return back()->with('error', 'Status permohonan kendaraan belum sesuai tahap verifikasi.');
            }

            $vehicleBooking->status = 'rejected';
            $msg = 'Peminjaman kendaraan ditolak.';
        } else {
            return back()->with('error', 'Fitur revisi tidak tersedia untuk kendaraan.');
        }

        $vehicleBooking->save();
        return back()->with('success', $msg);
    }

    public function processRoomAction(Request $request, $id)
    {
        $user = Auth::user();
        $roomBooking = RoomBooking::findOrFail($id);
        $action = $request->input('action');

        if (!in_array($user->role, ['staff_bidang', 'kepala_bidang', 'sekretariat'], true)) {
            return back()->with('error', 'Anda tidak berwenang memproses ruangan.');
        }

        if ($action === 'approve') {
            if ($roomBooking->status === 'pending' && $user->role === 'staff_bidang') {
                $roomBooking->status = 'staff_approved';
            } elseif ($roomBooking->status === 'pending' && $user->role === 'sekretariat') {
                $roomBooking->status = 'sekretariat_approved';
            } elseif (in_array($roomBooking->status, ['staff_approved', 'sekretariat_approved'], true) && $user->role === 'kepala_bidang') {
                $roomBooking->status = 'final_approved';
            } else {
                return back()->with('error', 'Status booking ruangan belum sesuai tahap verifikasi.');
            }

            $msg = 'Peminjaman ruangan disetujui.';
        } elseif ($action === 'reject') {
            if (!(
                $roomBooking->status === 'pending' && in_array($user->role, ['staff_bidang', 'sekretariat'], true)
                || in_array($roomBooking->status, ['staff_approved', 'sekretariat_approved'], true) && $user->role === 'kepala_bidang'
            )) {
                return back()->with('error', 'Status booking ruangan belum sesuai tahap verifikasi.');
            }

            $roomBooking->status = 'rejected';
            $msg = 'Peminjaman ruangan ditolak.';
        } else {
            return back()->with('error', 'Fitur revisi tidak tersedia untuk ruangan.');
        }

        $roomBooking->save();
        return back()->with('success', $msg);
    }

    public function processBorrowAction(Request $request, $id)
    {
        $borrowRequest = BorrowRequest::findOrFail($id);
        $user = Auth::user();
        $action = $request->input('action');
        $comment = $request->input('comment');
        $newStatus = '';

        switch ($user->role) {
            case 'staff_bidang':
            case 'sekretariat':
                if ($borrowRequest->status != 'pending') {
                    return back()->with('error', 'Status permintaan sudah berubah atau tidak valid.');
                }
                if ($action === 'approve') $newStatus = $user->role === 'staff_bidang' ? 'staff_approved' : 'sekretariat_approved';
                elseif ($action === 'reject') $newStatus = 'rejected';
                else $newStatus = 'revision_requested';
                break;

            case 'kepala_bidang':
                if (!in_array($borrowRequest->status, ['staff_approved', 'sekretariat_approved'], true)) {
                    return back()->with('error', 'Status permintaan belum melewati verifikasi tahap pertama.');
                }
                if ($action === 'approve') $newStatus = 'final_approved';
                elseif ($action === 'reject') $newStatus = 'rejected';
                else $newStatus = 'revision_requested';
                break;

            default:
                return back()->with('error', 'Role Anda tidak memiliki akses.');
        }

        try {
            DB::transaction(function () use ($borrowRequest, $user, $action, $comment, $newStatus) {
                $borrowRequest->status = $newStatus;
                $borrowRequest->save();

                $borrowRequest->histories()->create([
                    'user_id' => $user->id,
                    'role' => $user->role,
                    'action' => $action,
                    'comment' => $comment ?? ($action == 'approve' ? 'Disetujui' : ''),
                ]);

                if ($newStatus === 'rejected') {
                    $borrowRequest->item->increment('jumlah', $borrowRequest->jumlah);
                }
            });

            return back()->with('success', 'Permintaan barang berhasil diproses.');
        } catch (\Exception $e) {
            return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
        }
    }

    public function processReturnAction(Request $request, $id)
    {
        $borrowRequest = BorrowRequest::findOrFail($id);
        $user = Auth::user();
        $action = $request->input('action');
        $comment = $request->input('comment');
        $finalCondition = $request->input('final_condition');

        if ($user->role !== 'sekretariat') {
            return back()->with('error', 'Hanya Sipian yang dapat memverifikasi pengembalian.');
        }

        try {
            DB::transaction(function () use ($borrowRequest, $user, $action, $comment, $finalCondition) {
                if ($action === 'approve') {
                    $borrowRequest->status = 'returned';

                    if ($finalCondition) {
                        $borrowRequest->return_condition = $finalCondition;
                    }

                    if ($finalCondition === 'baik' || $borrowRequest->return_condition === 'baik') {
                        $item = Item::lockForUpdate()->find($borrowRequest->item_id);
                        $item->increment('jumlah', $borrowRequest->jumlah);
                    }

                    $msgAction = 'return_approved';
                    $msgComment = $comment ?? 'Pengembalian diterima. Stok diperbarui.';
                } elseif ($action === 'reject') {
                    $borrowRequest->status = 'final_approved';
                    $msgAction = 'return_rejected';
                    $msgComment = $comment;
                } else {
                    return;
                }

                $borrowRequest->save();

                $borrowRequest->histories()->create([
                    'user_id' => $user->id,
                    'role' => $user->role,
                    'action' => $msgAction,
                    'comment' => $msgComment,
                ]);
            });

            return back()->with('success', 'Verifikasi pengembalian berhasil diproses.');
        } catch (\Exception $e) {
            return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
        }
    }

    public function processItemRequestAction(Request $request, $id)
    {
        $user = Auth::user();
        $action = $request->input('action');
        $comment = $request->input('comment');

        if (!in_array($user->role, ['staff_bidang', 'kepala_bidang'], true)) {
            abort(403);
        }

        try {
            DB::transaction(function () use ($id, $user, $action, $comment) {
                $itemRequest = ItemRequest::with('item')
                    ->lockForUpdate()
                    ->findOrFail($id);

                if ($user->role === 'staff_bidang') {
                    if ($itemRequest->status !== 'pending') {
                        throw new \Exception('Permintaan barang sudah melewati tahap staff.');
                    }

                    if ($action === 'approve') {
                        $itemRequest->status = 'staff_approved';
                    } elseif ($action === 'cancel') {
                        $itemRequest->status = 'cancelled';
                    } else {
                        throw new \Exception('Aksi tidak valid untuk permintaan barang.');
                    }

                    $itemRequest->admin_note = $comment;
                    $itemRequest->approved_by = $user->id;
                    $itemRequest->approved_at = now();
                    $itemRequest->save();

                    return;
                }

                if ($itemRequest->status !== 'staff_approved') {
                    throw new \Exception('Permintaan barang belum disetujui staff.');
                }

                if ($action === 'approve') {
                    $requestItem = RequestItem::lockForUpdate()->find($itemRequest->request_item_id);

                    if (!$requestItem) {
                        throw new \Exception('Data barang permintaan tidak ditemukan.');
                    }

                    if ((float) $requestItem->stock < (float) $itemRequest->quantity) {
                        throw new \Exception('Stok barang tidak mencukupi untuk disetujui.');
                    }

                    $requestItem->decrement('stock', $itemRequest->quantity);

                    $itemRequest->status = 'approved';
                    $itemRequest->admin_note = $comment;
                    $itemRequest->approved_by = $user->id;
                    $itemRequest->approved_at = now();
                    $itemRequest->save();
                } elseif ($action === 'cancel') {
                    $itemRequest->status = 'cancelled';
                    $itemRequest->admin_note = $comment;
                    $itemRequest->approved_by = $user->id;
                    $itemRequest->approved_at = now();
                    $itemRequest->save();
                } else {
                    throw new \Exception('Aksi tidak valid untuk permintaan barang.');
                }
            });

            return back()->with('success', 'Permintaan barang berhasil diproses.');
        } catch (\Exception $e) {
            return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
        }
    }
}
