<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Exports\WarrantyExport;
use App\Models\AssetWarranty;
use App\Services\WarrantyService;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Maatwebsite\Excel\Facades\Excel;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

/**
 * The warranty register: a full, filterable list of every coverage period
 * (`index`), and a read-only, urgency-grouped alerts view (`expiring`) for a
 * quick glance rather than a worklist. Both read from the same
 * WarrantyService the renewal-digest command uses, so "what's expiring soon"
 * never has two different definitions in the app.
 */
class WarrantyController extends Controller
{
    public function __construct(
        private readonly WarrantyService $warranties,
    ) {}

    public function index(Request $request): View
    {
        $filters = $this->filtersFrom($request);
        $days = $request->integer('days', max(WarrantyService::UI_BUCKETS));

        $warranties = AssetWarranty::query()
            ->with(['asset.category'])
            ->search($filters['search'])
            ->ofType($filters['type'])
            ->when($filters['status'] === 'expired', fn ($query) => $query->expired())
            ->when($filters['status'] === 'expiring', fn ($query) => $query->expiringWithin($days))
            ->when($filters['status'] === 'active', fn ($query) => $query->active())
            ->orderBy('end_date')
            ->paginate((int) setting('pagination_per_page', config('ams.pagination.per_page')))
            ->withQueryString();

        return view('warranty.index', [
            'warranties' => $warranties,
            'filters' => $filters,
            'cards' => $this->cardCounts(),
        ]);
    }

    /**
     * Three mutually exclusive buckets, matching the urgency grouping every
     * warranty-tracking tool converges on: overdue action, action needed
     * soon, and everything else that's fine for now.
     */
    public function expiring(): View
    {
        $withinFurthestBucket = $this->warranties->expiringWithin(max(WarrantyService::UI_BUCKETS));

        return view('warranty.expiring', [
            'critical' => $withinFurthestBucket->filter(fn (AssetWarranty $w): bool => $w->daysRemaining() <= 30)->values(),
            'upcoming' => $withinFurthestBucket->reject(fn (AssetWarranty $w): bool => $w->daysRemaining() <= 30)->values(),
            'expired' => $this->warranties->expired(),
        ]);
    }

    public function export(Request $request): BinaryFileResponse
    {
        $export = new WarrantyExport($this->filtersFrom($request));

        return Excel::download($export, 'aumni-ams-warranties-'.now()->format('Y-m-d-His').'.xlsx');
    }

    /**
     * @return array<string, int>
     */
    private function cardCounts(): array
    {
        $counts = [
            'active' => AssetWarranty::query()->active()->count(),
            'expired' => AssetWarranty::query()->expired()->count(),
        ];

        foreach (WarrantyService::UI_BUCKETS as $days) {
            $counts['expiring_'.$days] = AssetWarranty::query()->expiringWithin($days)->count();
        }

        return $counts;
    }

    /**
     * @return array<string, string>
     */
    private function filtersFrom(Request $request): array
    {
        return [
            'search' => $request->string('search')->toString(),
            'type' => $request->string('type')->toString(),
            'status' => $request->string('status')->toString(),
        ];
    }
}
