<?php

namespace App\Http\Controllers;

use App\Models\Category;
use App\Models\InventoryItem;
use App\Models\Room;
use App\Models\ScanActivity;
use App\Support\AdminRealtimeNotifier;
use App\Support\ItemQrPdf;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;

class InventoryItemController extends Controller
{
    public function index(Request $request)
    {
        $query = InventoryItem::with(['category', 'room'])->latest();

        if ($request->filled('search')) {
            $search = $request->string('search');
            $query->where(function ($builder) use ($search) {
                $builder->where('nama_barang', 'like', "%{$search}%")
                    ->orWhere('kode_aset', 'like', "%{$search}%");
            });
        }

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

        $items = $query->get();
        $statuses = $this->statuses();

        return view('items.index', compact('items', 'statuses'));
    }

    public function create()
    {
        $categories = Category::orderBy('nama_kategori')->get();
        $rooms = Room::orderBy('nama_ruangan')->get();
        $statuses = $this->statuses();

        return view('items.create', compact('categories', 'rooms', 'statuses'));
    }

    public function store(Request $request)
    {
        $data = $this->validatedData($request);
        $data['pengajuan_penggantian'] = $data['status_barang'] === 'replace' || $request->boolean('replacement_requested');
        $data['lokasi_foto'] = $this->storePhoto($request);

        InventoryItem::create($data);

        return redirect()->route('items.index')->with('success', 'Barang berhasil ditambahkan.');
    }

    public function show(InventoryItem $item)
    {
        $item->load(['category', 'room']);

        return view('items.show', compact('item'));
    }

    public function edit(InventoryItem $item)
    {
        $categories = Category::orderBy('nama_kategori')->get();
        $rooms = Room::orderBy('nama_ruangan')->get();
        $statuses = $this->statuses();

        return view('items.edit', compact('item', 'categories', 'rooms', 'statuses'));
    }

    public function update(Request $request, InventoryItem $item)
    {
        $data = $this->validatedData($request, $item);
        $data['pengajuan_penggantian'] = $data['status_barang'] === 'replace' || $request->boolean('replacement_requested');

        if ($request->hasFile('photo')) {
            $this->deletePhoto($item->lokasi_foto);
            $data['lokasi_foto'] = $this->storePhoto($request);
        }

        $item->update($data);

        return redirect()->route('items.index')->with('success', 'Barang berhasil diperbarui.');
    }

    public function destroy(InventoryItem $item)
    {
        $this->deletePhoto($item->lokasi_foto);
        $item->delete();

        return redirect()->route('items.index')->with('success', 'Barang berhasil dihapus.');
    }

    public function scan(Request $request, InventoryItem $item)
    {
        $officer = $request->input('officer_name', 'Petugas Mobile');

        ScanActivity::create([
            'id_ruangan' => $item->id_ruangan,
            'id_barang' => $item->id,
            'nama_petugas' => $officer,
            'aktivitas' => 'scan',
            'deskripsi' => $item->nama_barang . ' dipindai oleh ' . $officer,
            'dipindai_pada' => Carbon::now(),
        ]);

        AdminRealtimeNotifier::itemScan($item, $officer);

        return back()->with('success', 'Aktivitas scan barang berhasil dicatat.');
    }

    public function qrPdf(InventoryItem $item, ItemQrPdf $pdf)
    {
        $filename = 'qr-barang-' . Str::slug($item->kode_aset ?: $item->nama_barang) . '.pdf';

        return response($pdf->render($item), 200, [
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => 'inline; filename="' . $filename . '"',
        ]);
    }

    private function validatedData(Request $request, ?InventoryItem $item = null): array
    {
        $data = $request->validate([
            'category_id' => ['required', 'exists:categories,id'],
            'room_id' => ['required', 'exists:rooms,id'],
            'name' => ['required', 'string', 'max:180'],
            'asset_code' => ['required', 'string', 'max:40', Rule::unique('inventory_items', 'kode_aset')->ignore($item)],
            'acquisition_year' => ['required', 'integer', 'min:1980', 'max:' . (date('Y') + 1)],
            'useful_life_years' => ['required', 'integer', 'min:1', 'max:30'],
            'status' => ['required', Rule::in(array_keys($this->statuses()))],
            'maintenance_due_date' => ['nullable', 'date'],
            'replacement_requested' => ['nullable', 'boolean'],
            'notes' => ['nullable', 'string', 'max:1000'],
            'photo' => ['nullable', 'image', 'max:4096'],
        ]);

        return [
            'id_kategori' => $data['category_id'],
            'id_ruangan' => $data['room_id'],
            'nama_barang' => $data['name'],
            'kode_aset' => $data['asset_code'],
            'tahun_perolehan' => $data['acquisition_year'],
            'umur_manfaat_tahun' => $data['useful_life_years'],
            'status_barang' => $data['status'],
            'tanggal_jadwal_pemeliharaan' => $data['maintenance_due_date'] ?? null,
            'catatan' => $data['notes'] ?? null,
        ];
    }

    private function storePhoto(Request $request): ?string
    {
        if (! $request->hasFile('photo')) {
            return null;
        }

        return $request->file('photo')->store('items', 'public');
    }

    private function deletePhoto(?string $path): void
    {
        if ($path) {
            Storage::disk('public')->delete($path);
        }
    }

    private function statuses(): array
    {
        return [
            'good' => 'Baik',
            'maintenance' => 'Perawatan',
            'broken' => 'Rusak',
            'replace' => 'Ganti',
        ];
    }
}
