<?php
namespace EasyChat\Library\Email;

 
final class EmailConnectionProbe {
    public function probe(array $account): array {
        $private = !empty($account['allow_private_server']);
        $imap = $this->endpoint($account, 'imap', $private);
        $smtp = $this->endpoint($account, 'smtp', $private);
        if (!$imap || !$smtp) return ['success'=>false, 'error'=>'email_endpoint_invalid'];
        try {
            $imapGreeting = $this->greeting($imap['host'], $imap['port'], '*', $private);
            $smtpGreeting = $smtp['port'] === 587
                ? $this->startTlsGreeting($smtp['host'], $smtp['port'], $private)
                : $this->greeting($smtp['host'], $smtp['port'], '220', $private);
            return [
                'success'=>true,
                'imap'=>strpos($imapGreeting, '*') === 0,
                'smtp'=>strpos($smtpGreeting, '220') === 0,
                'tls'=>true,
            ];
        } catch (\Throwable $e) {
            return ['success'=>false, 'error'=>'email_tls_connection_failed'];
        }
    }

    private function endpoint(array $data, string $kind, bool $private): array {
        $host = EmailEndpoint::normalizeHost((string)($data[$kind . '_host'] ?? ''), $private);
        $port = EmailEndpoint::normalizePort($data[$kind . '_port'] ?? 0, $kind);
        return $host !== '' && $port > 0 ? ['host'=>$host, 'port'=>$port] : [];
    }

    private function greeting(string $host, int $port, string $prefix, bool $private = false): string {
        $ip=EmailEndpoint::resolveAddress($host,$private);if($ip==='')throw new \RuntimeException('email_dns_failed');
        $context = stream_context_create(['ssl'=>[
            'verify_peer'=>true, 'verify_peer_name'=>true, 'allow_self_signed'=>false,
            'peer_name'=>$host, 'SNI_enabled'=>true, 'disable_compression'=>true,
        ]]);
        $errno = 0; $error = '';
        $socket = @stream_socket_client('tls://' . EmailEndpoint::socketHost($ip) . ':' . $port, $errno, $error, 8, STREAM_CLIENT_CONNECT, $context);
        if (!$socket) throw new \RuntimeException('email_connect_failed');
        stream_set_timeout($socket, 8);
        $line = (string)fgets($socket, 2048);
        fclose($socket);
        if (strpos($line, $prefix) !== 0) throw new \RuntimeException('email_greeting_invalid');
        return $line;
    }

    private function startTlsGreeting(string $host, int $port, bool $private = false): string {
        $ip=EmailEndpoint::resolveAddress($host,$private);if($ip==='')throw new \RuntimeException('email_dns_failed');
        $context = stream_context_create(['ssl'=>['verify_peer'=>true,'verify_peer_name'=>true,'allow_self_signed'=>false,'peer_name'=>$host,'SNI_enabled'=>true]]);
        $errno=0; $error='';
        $socket=@stream_socket_client('tcp://'.EmailEndpoint::socketHost($ip).':'.$port,$errno,$error,8,STREAM_CLIENT_CONNECT,$context);
        if (!$socket) throw new \RuntimeException('smtp_connect_failed');
        stream_set_timeout($socket,8);
        $greeting=(string)fgets($socket,2048);
        fwrite($socket,"EHLO easychat.local\r\n");
        do { $line=(string)fgets($socket,2048); } while (isset($line[3]) && $line[3]==='-');
        fwrite($socket,"STARTTLS\r\n");
        $ready=(string)fgets($socket,2048);
        $secured=strpos($greeting,'220')===0 && strpos($ready,'220')===0 && stream_socket_enable_crypto($socket,true,STREAM_CRYPTO_METHOD_TLS_CLIENT);
        fclose($socket);
        if (!$secured) throw new \RuntimeException('smtp_starttls_failed');
        return $greeting;
    }
}
