<?php
namespace EasyChat\Library\Email;

 
final class RawEmailParser {
    public function parse(string $raw): array {
        if($raw===''||strlen($raw)>8*1024*1024)throw new \RuntimeException('email_raw_invalid');
        $parts=preg_split("/\r?\n\r?\n/",$raw,2);$headers=$this->headers((string)($parts[0]??''));$body=(string)($parts[1]??'');
        $encoding=strtolower((string)($headers['content-transfer-encoding']??''));
        if($encoding==='base64')$body=(string)base64_decode(preg_replace('/\s+/','',$body),true);
        elseif($encoding==='quoted-printable')$body=quoted_printable_decode($body);
        $contentType=strtolower((string)($headers['content-type']??'text/plain'));
        if(strpos($contentType,'text/html')!==false)$body=html_entity_decode(strip_tags(preg_replace('#<(?:br|/p|/div)\b[^>]*>#i',"\n",$body)),ENT_QUOTES|ENT_HTML5,'UTF-8');
        if(strpos($contentType,'multipart/')!==false)$body=$this->firstTextPart($raw,$contentType);
        $from=$this->address((string)($headers['from']??''));$reply=$this->address((string)($headers['reply-to']??''));
        $messageId=trim((string)($headers['message-id']??''),' <>');
        return ['from'=>$from['email'],'display_name'=>$from['name'],'reply_to'=>$reply['email'],'subject'=>$this->decodeHeader((string)($headers['subject']??'')),'message_id'=>$messageId,'in_reply_to'=>trim((string)($headers['in-reply-to']??''),' <>'),'references'=>(string)($headers['references']??''),'text'=>trim($body),'auto_submitted'=>strtolower((string)($headers['auto-submitted']??''))];
    }
    private function headers(string $raw): array { $raw=preg_replace("/\r?\n[ \t]+/",' ',$raw);$out=[];foreach(preg_split('/\r?\n/',$raw) as $line){$p=strpos($line,':');if($p===false)continue;$out[strtolower(trim(substr($line,0,$p)))]=trim(substr($line,$p+1));}return $out; }
    private function address(string $value): array {
        $value=trim(preg_replace('/[\r\n\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/',' ', $value));
        $name='';$email='';
         
         
        if(function_exists('imap_rfc822_parse_adrlist')){
            $addresses=@imap_rfc822_parse_adrlist($value,'');
            if(is_array($addresses))foreach($addresses as $address){
                $mailbox=(string)($address->mailbox??'');$host=(string)($address->host??'');
                if($mailbox!==''&&$host!==''&&$mailbox!=='INVALID_ADDRESS'){$email=strtolower($mailbox.'@'.$host);$name=(string)($address->personal??'');break;}
            }
        }
        if($email===''&&preg_match('/^(.*?)<\s*([^<>\s]+@[^<>\s]+)\s*>$/u',$value,$m)){$name=(string)$m[1];$email=strtolower(trim($m[2]));}
        elseif($email==='')$email=strtolower(trim($value," \t\"'<>"));
        if(strpos($name,'=?')!==false)$name=$this->decodeHeader($name);
        $name=trim(preg_replace('/\s+/u',' ',trim($name," \t\"'")));
        if(strtolower($name)===$email)$name='';
        $name=function_exists('mb_substr')?mb_substr($name,0,128,'UTF-8'):substr($name,0,128);
        return ['name'=>$name,'email'=>filter_var($email,FILTER_VALIDATE_EMAIL)?$email:''];
    }
    private function decodeHeader(string $value): string { if(!function_exists('iconv_mime_decode'))return $value;$decoded=(string)@iconv_mime_decode($value,ICONV_MIME_DECODE_CONTINUE_ON_ERROR,'UTF-8');return $decoded!==''||$value===''?$decoded:$value; }
    private function firstTextPart(string $raw,string $contentType): string { if(!preg_match('/boundary\s*=\s*(?:"([^"]+)"|([^;\s]+))/i',$contentType,$m))return '';$boundary=preg_quote((string)($m[1]?:$m[2]),'#');$parts=preg_split('#--'.$boundary.'(?:--)?\r?\n#',$raw);foreach($parts as $part){if(stripos($part,'Content-Type: text/plain')!==false){$split=preg_split("/\r?\n\r?\n/",$part,2);$body=(string)($split[1]??'');if(stripos($part,'quoted-printable')!==false)$body=quoted_printable_decode($body);if(stripos($part,'base64')!==false)$body=(string)base64_decode(preg_replace('/\s+/','',$body),true);return trim($body);}}return ''; }
}
