<?php

namespace App\Services;

use App\Util;

class CoinPay
{
    protected $config;
    protected $key;
    protected $appId;
    protected $apiUrl;
    protected $version;

    public function __construct(string $configKey = 'CoinPay')
    {
        $payConfig = new PayConfig();
        $this->config = $payConfig->getConfig($configKey);

        $this->key = $this->config['key'] ?? '';
        $this->appId = $this->config['appId'] ?? '';
        $this->apiUrl = rtrim($this->config['apiUrl'] ?? '', '/');
        $this->version = $this->config['version'] ?? 'v1';
    }

    public function getConfig(): array
    {
        return $this->config;
    }

    public function sign(array $params): array
    {
        if (!isset($params['appId']) && $this->appId) {
            $params['appId'] = $this->appId;
        }
        $params['sign'] = $this->generateSign($params);
        return $params;
    }

    public function verify(array $params): bool
    {
        if (!isset($params['sign'])) {
            return false;
        }

        $received = strtolower($params['sign']);
        unset($params['sign']);

        if (!isset($params['appId']) && $this->appId) {
            $params['appId'] = $this->appId;
        }

        return $received === $this->generateSign($params);
    }

    public function post(string $path, array $payload)
    {
        $url = $this->apiUrl . $path;
        $headers = [
            'Content-Type: application/json; charset=UTF-8',
            'version: ' . $this->version,
            'appId: ' . $this->appId,
        ];

        $body = json_encode($payload, JSON_UNESCAPED_UNICODE);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $result = curl_exec($ch);
        if (curl_errno($ch)) {
            Util::WriteLog('CoinPay_error', 'CURL Error: ' . curl_error($ch));
        }
        curl_close($ch);

        return $result;
    }

    protected function generateSign(array $params): string
    {
        $filtered = [];
        foreach ($params as $key => $value) {
            if ($key === 'sign') {
                continue;
            }
            if ($value === null || $value === '') {
                continue;
            }
            if (is_array($value)) {
                $value = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            }
            $filtered[$key] = $value;
        }

        ksort($filtered);
        $segments = [];
        foreach ($filtered as $key => $value) {
            $segments[] = $key . '=' . $value;
        }
        $segments[] = 'key=' . $this->key;

        $string = implode('&', $segments);

        return strtolower(hash('sha256', $string));
    }
}

