<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Asset;
use App\Models\AssetType;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class AssetController extends Controller
{
    public function dashboard()
    {
        $companyId = Auth::user()?->company_id;
        $baseQuery = Asset::query();
        if ($companyId) {
            $baseQuery->where('company_id', $companyId);
        }

        $totalAssets = (clone $baseQuery)->count();

        $byStatus = (clone $baseQuery)->select('status', DB::raw('count(*) as total'))
            ->groupBy('status')
            ->pluck('total', 'status')
            ->toArray();

        $statusKeys = ['available', 'assigned', 'maintenance', 'retired'];
        foreach ($statusKeys as $key) {
            $byStatus[$key] = $byStatus[$key] ?? 0;
        }

        $byType = AssetType::withCount(['assets' => function ($q) use ($companyId) {
            if ($companyId) {
                $q->where('company_id', $companyId);
            }
        }])
            ->having('assets_count', '>', 0)
            ->orderByDesc('assets_count')
            ->get(['name', 'id'])
            ->map(fn ($t) => ['name' => $t->name, 'count' => $t->assets_count])
            ->values()
            ->toArray();

        $recentAssets = (clone $baseQuery)->with(['assetType', 'assignedUser'])
            ->orderByDesc('created_at')
            ->limit(5)
            ->get();

        $assignedPct = $totalAssets > 0
            ? round(($byStatus['assigned'] / $totalAssets) * 100)
            : 0;

        return view('assets.dashboard', compact(
            'totalAssets',
            'byStatus',
            'byType',
            'recentAssets',
            'assignedPct'
        ));
    }

    public function index()
    {
        $companyId = Auth::user()?->company_id;
        $query = Asset::with(['assetType', 'assignedUser'])->orderBy('name');
        if ($companyId) {
            $query->where('company_id', $companyId);
        }
        $assets = $query->paginate(15);

        return view('assets.index', compact('assets'));
    }

    public function create()
    {
        $assetTypes = AssetType::orderBy('name')->get();
        $users = User::forActiveDirectory();
        if (auth()->user()->company_id) {
            $users->where('company_id', auth()->user()->company_id);
        }
        $users = $users->orderBy('name')->get();

        return view('assets.create', compact('assetTypes', 'users'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:191',
            'asset_type_id' => 'nullable|exists:asset_types,id',
            'serial_number' => 'nullable|string|max:100',
            'assigned_to' => 'nullable|exists:users,id',
            'status' => 'required|in:available,assigned,maintenance,retired',
            'purchase_date' => 'nullable|date',
            'notes' => 'nullable|string|max:1000',
        ]);
        $validated['company_id'] = auth()->user()->company_id;
        if (! empty($validated['assigned_to'])) {
            $validated['status'] = 'assigned';
        }
        Asset::create($validated);

        return redirect()->route('assets.index')->with('success', 'Asset created successfully.');
    }

    public function edit(Asset $asset)
    {
        $this->authorizeAsset($asset);
        $assetTypes = AssetType::orderBy('name')->get();
        $users = User::forActiveDirectory();
        if (auth()->user()->company_id) {
            $users->where('company_id', auth()->user()->company_id);
        }
        $users = $users->orderBy('name')->get();

        return view('assets.edit', compact('asset', 'assetTypes', 'users'));
    }

    public function update(Request $request, Asset $asset)
    {
        $this->authorizeAsset($asset);
        $validated = $request->validate([
            'name' => 'required|string|max:191',
            'asset_type_id' => 'nullable|exists:asset_types,id',
            'serial_number' => 'nullable|string|max:100',
            'assigned_to' => 'nullable|exists:users,id',
            'status' => 'required|in:available,assigned,maintenance,retired',
            'purchase_date' => 'nullable|date',
            'notes' => 'nullable|string|max:1000',
        ]);

        if (! empty($validated['assigned_to'])) {
            $validated['status'] = $validated['status'] === 'retired' ? 'retired' : 'assigned';
        } elseif ($validated['status'] === 'assigned') {
            $validated['status'] = 'available';
        }

        $asset->update($validated);

        return redirect()->route('assets.index')->with('success', 'Asset updated successfully.');
    }

    public function destroy(Asset $asset)
    {
        $this->authorizeAsset($asset);
        $asset->delete();

        return redirect()->route('assets.index')->with('success', 'Asset removed successfully.');
    }

    public function returnAsset(Asset $asset)
    {
        $this->authorizeAsset($asset);
        $asset->update([
            'assigned_to' => null,
            'status' => 'available',
            'notes' => trim(($asset->notes ?? '') . "\nReturned on " . now()->format('Y-m-d')),
        ]);

        return redirect()->back()->with('success', 'Asset marked as returned.');
    }

    public function dispose(Asset $asset)
    {
        $this->authorizeAsset($asset);
        $asset->update([
            'assigned_to' => null,
            'status' => 'retired',
            'notes' => trim(($asset->notes ?? '') . "\nDisposed on " . now()->format('Y-m-d')),
        ]);

        return redirect()->back()->with('success', 'Asset disposed (retired).');
    }

    protected function authorizeAsset(Asset $asset): void
    {
        $companyId = Auth::user()?->company_id;
        if ($companyId && $asset->company_id !== $companyId) {
            abort(403);
        }
    }
}
