<?php

declare(strict_types=1);

namespace app\api\controller;

use app\common\controller\Api;
use app\common\facade\Token;
use ba\Random;
use Webman\Http\Request;
use support\Response;

use function response;

class V1 extends Api
{
    public function authToken(Request $request): Response
    {
        $responseInit = $this->initializeApi($request);
        if ($responseInit !== null) {
            return $responseInit;
        }

        $secret = trim((string) $request->get('secret', ''));
        $timestampRaw = $request->get('timestamp', '');
        $deviceId = trim((string) $request->get('device_id', ''));
        $signature = trim((string) $request->get('signature', ''));

        if ($secret === '' || $timestampRaw === '' || $deviceId === '' || $signature === '') {
            return $this->mobileResult(1001, 'Missing parameters');
        }

        $serverSecret = (string) env('AUTH_TOKEN_SECRET', '');
        if ($serverSecret === '' || !hash_equals($serverSecret, $secret)) {
            return $this->mobileResult(1103, 'Invalid secret');
        }

        $timestamp = filter_var($timestampRaw, FILTER_VALIDATE_INT);
        if ($timestamp === false) {
            return $this->mobileResult(1002, 'Invalid parameter format');
        }
        $now = time();
        $skew = abs($now - $timestamp);
        if ($skew > 300) {
            return $this->mobileResult(3001, 'Invalid timestamp');
        }

        $params = [
            'device_id' => $deviceId,
            'secret' => $secret,
            'timestamp' => (string) $timestamp,
        ];
        ksort($params);
        $pairs = [];
        foreach ($params as $k => $v) {
            $pairs[] = $k . '=' . $v;
        }
        $plain = implode('&', $pairs);
        $expected = strtoupper(md5($plain));
        if (!hash_equals($expected, $signature)) {
            return $this->mobileResult(1103, 'Invalid signature');
        }

        $token = Random::uuid();
        $expire = 60 * 60 * 24;
        Token::set($token, 'auth-token', 0, $expire);

        return $this->mobileResult(1, 'ok', [
            'auth_token' => $token,
            'expires_in' => $expire,
            'server_time' => $now,
        ]);
    }

    private function mobileResult(int $code, string $message, array $data = []): Response
    {
        $payload = [
            'code' => $code,
            'message' => __($message),
            'data' => $data,
        ];
        return response(json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), 200, ['Content-Type' => 'application/json']);
    }
}

