<?php

namespace App\Libraries\MySocket;

use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Cookie\CookieJar;
use Cloudflare\API\Adapter\ResponseException;

abstract class MySocket
{
    private $_cookieJar = null;
    protected function __construct() {}
    abstract public function getClient(): mixed;
    final protected function getCookieJar(): CookieJar
    {
        if (!$this->_cookieJar) {
            $this->_cookieJar = new CookieJar();
        }
        return $this->_cookieJar;
    }
    protected function getUserAgent(): string
    {
        // User-Agent 목록 배열
        $userAgents = [
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0',
            'Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1',
            'Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36'
        ];
        return $userAgents[array_rand($userAgents)];
    }
    protected function getRequestOptions(string $method, array $options = [], array $headers = []): array
    {
        //cookies->쿠키값 , timeout->5초 안에 응답이 없으면 타임아웃
        //method가 get이면 $request['query'] = $options , 다른것이면 $request['json] = $options
        $options = [
            // 'cookies' => $this->getCookieJar(),
            'timeout' => env("socket.web.timeout") ?? 5,
            'headers' => $headers,
            in_array($method, ['get']) ? 'query' : 'json' => $options
        ];
        return $options;
    }
    public function request(string $method, $uri = '', array $options = [], array $headers = []): ResponseInterface
    {
        if (!in_array($method, ['get', 'post', 'put', 'patch', 'delete'])) {
            throw new \InvalidArgumentException("{$method} => Request method must be get, post, put, patch, or delete");
        }
        try {
            $options = $this->getRequestOptions($method, $options, $headers);
            $response = $this->getClient()->$method($uri, $options);
            $body = json_decode(json: $response->getBody());
            if (!$body->success) {
                $message = sprintf(
                    "%s에서 {$uri} 실패:\nrequest:%s\nresponse:%s",
                    $method,
                    $uri,
                    var_export($options, true),
                    var_export($response, true)
                );
                log_message("error", $message);
                throw new ResponseException($message);
            }
            return $response;
        } catch (RequestException $err) {
            throw ResponseException::fromRequestException($err);
        }
    }
    final public function get($uri, array $options = [], array $headers = []): ResponseInterface
    {
        return $this->request(__FUNCTION__, $uri, $options, $headers);
    }
    final public function post($uri, array $options = [], array $headers = []): ResponseInterface
    {
        return $this->request(__FUNCTION__, $uri, $options, $headers);
    }
    final public function put($uri, array $options = [], array $headers = []): ResponseInterface
    {
        return $this->request(__FUNCTION__, $uri, $options, $headers);
    }
    final public function patch($uri, array $options = [], array $headers = []): ResponseInterface
    {
        return $this->request(__FUNCTION__, $uri, $options, $headers);
    }
    final public function delete($uri, array $options = [], array $headers = []): ResponseInterface
    {
        return $this->request(__FUNCTION__, $uri, $options, $headers);
    }
}
