<?php
declare(strict_types=1);

final class ItzCommerceClient
{
    public function __construct(
        private string $endpoint,
        private string $apiKey,
        private string $secret,
        private int $timeout = 15,
    ) { $this->endpoint=rtrim($this->endpoint,'/'); }

    public function call(string $action,array $payload=[]): array
    {
        $payload['action']=$action;
        $body=json_encode($payload,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
        if($body===false)throw new RuntimeException('Unable to encode commerce request.');
        $ts=(string)time();$sig=hash_hmac('sha256',$ts."\n".$body,$this->secret);
        $ch=curl_init($this->endpoint);
        if(!$ch)throw new RuntimeException('Unable to initialise cURL.');
        curl_setopt_array($ch,[CURLOPT_RETURNTRANSFER=>true,CURLOPT_POST=>true,CURLOPT_POSTFIELDS=>$body,CURLOPT_CONNECTTIMEOUT=>5,CURLOPT_TIMEOUT=>$this->timeout,CURLOPT_HTTPHEADER=>['Content-Type: application/json','X-iTz-Key: '.$this->apiKey,'X-iTz-Timestamp: '.$ts,'X-iTz-Signature: '.$sig]]);
        $raw=curl_exec($ch);$errno=curl_errno($ch);$error=curl_error($ch);$code=(int)curl_getinfo($ch,CURLINFO_HTTP_CODE);curl_close($ch);
        if($raw===false)throw new RuntimeException("Commerce transport error #{$errno}: {$error}");
        $data=json_decode($raw,true);if(!is_array($data))throw new RuntimeException("Invalid Commerce response (HTTP {$code}).");
        if($code<200||$code>=300||empty($data['ok']))throw new RuntimeException((string)($data['message']??$data['error']??"HTTP {$code}"));
        return $data;
    }

    public function catalog(): array { return $this->call('catalog')['products']??[]; }
    public function paymentMethods(): array { return $this->call('payment.methods')['methods']??[]; }
    public function createOrder(array $order): array { return $this->call('order.create',$order); }
    public function submitParameters(string $publicId,array $parameters): array { return $this->call('order.parameters',['public_id'=>$publicId,'parameters'=>$parameters]); }
    public function paymentSuccess(string $publicId,string $method,string $reference,array $meta=[]): array { return $this->call('payment.success',['public_id'=>$publicId,'payment_method'=>$method,'payment_ref'=>$reference,'meta'=>$meta]); }
    public function paymentFailed(string $publicId,string $method,array $meta=[]): array { return $this->call('payment.failed',['public_id'=>$publicId,'payment_method'=>$method,'meta'=>$meta]); }
    public function orderStatus(string $publicId): array { return $this->call('order.status',['public_id'=>$publicId]); }
}
