<?php
namespace EasyChat\Library\Email;

use EasyChat\Library\Http\ExternalHttpClient;

 
final class SmtpBzApiTransport implements OutboundMailTransportInterface {
    const API_BASE = 'https://api.smtp.bz/v1';
    private $registry;
    public function __construct($registry = null) { $this->registry = $registry; }
    public function code(): string { return 'smtp_bz_api'; }

    public function probe(array $config): array {
        $key = trim((string)($config['smtp_bz_api_key'] ?? ''));
        $domain = substr(strrchr((string)($config['sender_email'] ?? $config['email_address'] ?? ''), '@') ?: '', 1);
        if ($key === '' || $domain === '') return array('success'=>false,'status'=>'error','code'=>'smtp_bz_credentials_required','transport'=>$this->code());
        $result = $this->request('GET', '/user/domain/' . rawurlencode($domain), $key);
        if (empty($result['transport_ok'])) return array('success'=>false,'status'=>'error','code'=>'smtp_bz_unreachable','transport'=>$this->code());
        $status = (int)($result['http_code'] ?? 0);
        if ($status === 401) return array('success'=>false,'status'=>'error','code'=>'smtp_bz_auth_failed','transport'=>$this->code());
        if ($status < 200 || $status >= 300) return array('success'=>false,'status'=>'error','code'=>'smtp_bz_domain_unverified','transport'=>$this->code());
        return array('success'=>true,'status'=>'ready','code'=>'smtp_bz_ready','transport'=>$this->code());
    }

    public function send(array $config, MailEnvelope $mail): array {
        $key = trim((string)($config['smtp_bz_api_key'] ?? ''));
        if ($key === '') return array('success'=>false,'error'=>'smtp_bz_credentials_required','retryable'=>false);
        $additional = array();
        if ($mail->messageId() !== '') $additional[] = array('Message-ID'=>'<' . $mail->messageId() . '>');
        if ($mail->inReplyTo() !== '') $additional[] = array('In-Reply-To'=>'<' . $mail->inReplyTo() . '>');
        if ($mail->references()) $additional[] = array('References'=>implode(' ', array_map(function ($id) { return '<' . $id . '>'; }, $mail->references())));
        $fields = array(
            'from'=>$mail->from(),
            'name'=>$mail->fromName(),
            'subject'=>$mail->subject(),
            'to'=>$mail->to(),
            'reply'=>$mail->replyTo(),
            'html'=>nl2br(htmlspecialchars($mail->text(), ENT_QUOTES, 'UTF-8')),
            'text'=>$mail->text(),
            'tag'=>substr($mail->idempotencyKey(), 0, 64),
            'headers'=>json_encode($additional, JSON_UNESCAPED_SLASHES),
        );
        $result = $this->request('POST', '/smtp/send', $key, $fields);
        if (empty($result['transport_ok'])) return array('success'=>false,'error'=>'smtp_bz_transport_failed','retryable'=>true);
        $status = (int)($result['http_code'] ?? 0);
        $body = json_decode((string)($result['raw'] ?? ''), true);
        $provider_id = is_array($body) ? (string)($body['message_id'] ?? $body['id'] ?? $body['messageId'] ?? '') : '';
        if ($status === 429) return array('success'=>false,'error'=>'rate_limited','retryable'=>true,'retry_without_attempt'=>true,'retry_after_seconds'=>60,'http_code'=>$status);
        if ($status < 200 || $status >= 300) return array('success'=>false,'error'=>$status >= 500?'smtp_bz_unavailable':'smtp_bz_rejected','retryable'=>$status >= 500,'http_code'=>$status);
        return array('success'=>true,'external_message_id'=>$provider_id !== ''?$provider_id:$mail->messageId(),'provider_message_id'=>$provider_id,'delivery_state'=>'accepted_by_provider','transport'=>$this->code(),'http_code'=>$status);
    }

    private function request(string $method, string $path, string $key, array $fields = array()): array {
        $request = array(
            'headers'=>array('Authorization: ' . $key, 'Accept: application/json'),
            'connect_timeout'=>5,
            'timeout'=>15,
            'follow_location'=>false,
            'allow_tls_fallback'=>true,
            'trust_profile'=>'smtp_bz_api',
        );
        if ($fields) $request['post_fields'] = $fields;
        return (new ExternalHttpClient($this->registry))->request($method, self::API_BASE . $path, $request);
    }
}
