<?php

namespace Modules\MedOrganization\Services;

use Illuminate\Support\Facades\Notification;
use Modules\MedOrganization\Entities\OrgStaffLicense;
use Modules\MedOrganization\Notifications\LicenseExpiryNotification;

/**
 * License expiry sweep (spec §5 credentialing "expiry_alerts"):
 *   1. flips licenses whose expiry_date has passed to status=expired;
 *   2. collects licenses expiring within N days (config
 *      medorganization.license_alert_days, default 30) and sends ONE
 *      database notification per business to its admins (mirrors how
 *      Essentials notifies admins via ModuleUtil::get_admins()).
 *
 * Invoked by `php artisan medorg:license-expiry-alerts`, scheduled daily
 * from the service provider.
 */
class LicenseAlertService
{
    /**
     * @return array{expired: int, businesses_notified: int, expiring: int}
     */
    public function run(): array
    {
        $expiredByBusiness = $this->markExpired();

        $days = (int) config('medorganization.license_alert_days', 30);

        $expiring = OrgStaffLicense::expiringWithin($days)
            ->with('user')
            ->orderBy('expiry_date')
            ->get()
            ->groupBy('business_id');

        $notified = 0;
        $totalExpiring = 0;

        $businessIds = $expiring->keys()
            ->merge(array_keys($expiredByBusiness))
            ->unique();

        foreach ($businessIds as $businessId) {
            $licenses = $expiring->get($businessId, collect());
            $totalExpiring += $licenses->count();

            $payload = $licenses->map(function ($license) {
                return [
                    'user'           => optional($license->user)->user_full_name ?? ('#' . $license->user_id),
                    'license_type'   => $license->license_type,
                    'license_number' => $license->license_number,
                    'expiry_date'    => optional($license->expiry_date)->toDateString(),
                    'status'         => $license->status,
                ];
            })->values()->all();

            $expiredCount = $expiredByBusiness[$businessId] ?? 0;

            if (empty($payload) && $expiredCount === 0) {
                continue;
            }

            $admins = $this->admins((int) $businessId);
            if ($admins->isEmpty()) {
                continue;
            }

            Notification::send($admins, new LicenseExpiryNotification($payload, $expiredCount));
            $notified++;
        }

        return [
            'expired'             => array_sum($expiredByBusiness),
            'businesses_notified' => $notified,
            'expiring'            => $totalExpiring,
        ];
    }

    /**
     * Flip past-expiry licenses to expired.
     *
     * @return array<int, int> business_id => number of licenses expired
     */
    public function markExpired(): array
    {
        $past = OrgStaffLicense::pastExpiry()->get();

        $byBusiness = [];
        foreach ($past as $license) {
            $license->update(['status' => 'expired']);
            $byBusiness[$license->business_id] = ($byBusiness[$license->business_id] ?? 0) + 1;
        }

        return $byBusiness;
    }

    /** Business admins via the existing helper (Util::get_admins). */
    protected function admins(int $businessId)
    {
        try {
            return app(\App\Utils\ModuleUtil::class)->get_admins($businessId);
        } catch (\Throwable $e) {
            \Log::warning('MedOrganization: could not resolve admins for business ' . $businessId . ': ' . $e->getMessage());

            return collect();
        }
    }
}
