<?php

namespace App\Services;

use Illuminate\Support\Facades\Log;

class SsoService
{
    const TOKEN_TTL = 600;

    protected $finance;

    public function __construct(FinanceApiService $finance)
    {
        $this->finance = $finance;
    }

    public function generateToken($user, $schoolId = null)
    {
        $admissionNumber = $this->admissionNumber($user);
        $secret = $this->secret($schoolId);

        if ($admissionNumber === '' || $secret === '') {
            return '';
        }

        $now = time();
        $payload = [
            'adm' => $admissionNumber,
            'iat' => $now,
            'exp' => $now + self::TOKEN_TTL,
            'nonce' => bin2hex(random_bytes(16)),
        ];

        $json = json_encode($payload, JSON_UNESCAPED_SLASHES);
        if (!is_string($json) || $json === '') {
            return '';
        }

        $encodedPayload = $this->base64UrlEncode($json);
        $signature = hash_hmac('sha256', $encodedPayload, $secret);

        Log::debug('Finance SSO token generated.', [
            'admission_number_hash' => sha1($admissionNumber),
            'iat' => $payload['iat'],
            'exp' => $payload['exp'],
            'token_lifetime_seconds' => $payload['exp'] - $payload['iat'],
        ]);

        return $encodedPayload . '.' . $signature;
    }

    private function admissionNumber($user)
    {
        if (!$user) {
            return '';
        }

        if (!empty($user->admission_number)) {
            return trim((string) $user->admission_number);
        }

        return trim((string) optional($user->student)->admission_no);
    }

    private function secret($schoolId = null)
    {
        $settings = $this->finance->settings($schoolId);

        return trim((string) ($settings['sso_secret'] ?? config('finance.sso_secret', '')));
    }

    private function base64UrlEncode($value)
    {
        return rtrim(strtr(base64_encode((string) $value), '+/', '-_'), '=');
    }
}
