<?php

namespace App\Modules\Operations\Services;

use App\Models\User;
use App\Modules\Dashboard\Repositories\OperationalMetricsRepository;
use App\Modules\HR\Overtime\Repositories\OvertimeRequestRepository;
use App\Modules\HR\PermissionRequests\Repositories\PermissionRequestRepository;
use App\Modules\Operations\Repositories\OperationalControlCenterQueryRepository;
use App\Modules\Sales\Repositories\SalesOrderRepository;
use Illuminate\Support\Facades\Route;

final class WorkflowInboxAssembler
{
    public function __construct(
        private readonly OperationalControlCenterDashboardService $controlCenter,
        private readonly OperationalMetricsRepository $metrics,
        private readonly OperationalControlCenterQueryRepository $procurementOpsQueries,
        private readonly SalesOrderRepository $salesOrders,
        private readonly PermissionRequestRepository $permissionRequests,
        private readonly OvertimeRequestRepository $overtime,
    ) {}

    /**
     * @return array<string, mixed>
     */
    public function assemble(User $user): array
    {
        $tenantId = (int) ($user->tenant_id ?? 0);
        $ops = $user->can('operations.control.view') && $tenantId > 0
            ? $this->controlCenter->assemble($tenantId)
            : null;
        $hr = $tenantId > 0 && ($user->can('leave.view') || $user->can('attendance.view') || $user->can('overtime.view'))
            ? $this->metrics->snapshot($tenantId)
            : null;

        $pendingPermissions = $tenantId > 0 && $user->can('permission_requests.review')
            ? $this->permissionRequests->countPendingForTenant($tenantId)
            : null;
        $pendingOvertime = $tenantId > 0 && $user->can('overtime.review')
            ? $this->overtime->pendingCountForTenant($tenantId)
            : null;

        $procurementInbox = $this->procurementInbox($user, $tenantId);
        $salesInbox = $this->salesInbox($user, $tenantId);

        return [
            'ops' => $ops,
            'hr' => $hr,
            'pendingPermissions' => $pendingPermissions,
            'pendingOvertime' => $pendingOvertime,
            'procurementInbox' => $procurementInbox,
            'salesInbox' => $salesInbox,
            'leaveUrl' => Route::has('hr.leave.requests.index') ? route('hr.leave.requests.index') : null,
            'exceptionsUrl' => Route::has('hr.attendance.exceptions.index')
                ? route('hr.attendance.exceptions.index')
                : null,
            'permissionsUrl' => Route::has('hr.permission-requests.index')
                ? route('hr.permission-requests.index')
                : null,
            'overtimeUrl' => Route::has('hr.overtime.index') ? route('hr.overtime.index') : null,
        ];
    }

    /**
     * @return array<string, mixed>|null
     */
    private function procurementInbox(User $user, int $tenantId): ?array
    {
        if ($tenantId <= 0) {
            return null;
        }
        $po = $user->can('procurement.purchase_orders.view');
        $gr = $user->can('procurement.goods_receipts.view');
        if (! $po && ! $gr) {
            return null;
        }
        $draftH = (int) config('operations-control.stale.draft_hours', 48);
        $valH = (int) config('operations-control.stale.validated_hours', 24);

        return [
            'pendingPos' => $po ? $this->procurementOpsQueries->purchaseOrdersAwaitingApproval($tenantId) : collect(),
            'staleValidated' => $gr ? $this->procurementOpsQueries->staleValidatedReceipts($tenantId, $valH) : collect(),
            'failedReceipts' => $gr ? $this->procurementOpsQueries->failedReceipts($tenantId) : collect(),
            'staleDrafts' => $gr ? $this->procurementOpsQueries->staleDraftReceipts($tenantId, $draftH) : collect(),
            'validatedStaleHours' => $valH,
            'draftStaleHours' => $draftH,
        ];
    }

    /**
     * @return \Illuminate\Database\Eloquent\Collection<int, \App\Modules\Sales\Models\SalesOrder>|null
     */
    private function salesInbox(User $user, int $tenantId)
    {
        if ($tenantId <= 0 || ! $user->can('sales.orders.view')) {
            return null;
        }

        return $this->salesOrders->recentDraftOrdersForTenant($tenantId);
    }
}
