<?php
namespace EasyChat\Library\Queue\Jobs;

use EasyChat\Library\Email\EmailReplyCleaner;
use EasyChat\Library\Email\ImapConnector;
use EasyChat\Library\Email\RawEmailParser;
use EasyChat\Library\Email\EmailThreadIndex;
use EasyChat\Library\Messenger\InboundService;
use EasyChat\Library\Messenger\MessengerLogger;
use EasyChat\Model\EmailAccount;
use EasyChat\Model\Messenger;

final class EmailSyncJob {
    private $registry;
    public function __construct($registry){$this->registry=$registry;}
    public function handle(array $payload): void {
        $channelId=(int)($payload['channel_id']??0);$model=new EmailAccount($this->registry);$account=$model->get(true);
        if(!$account||$channelId!==(int)$account['channel_id']||($account['status']??'')!=='active')return;
        $initialized=!empty($account['imap_cursor_initialized']);$lastUid=max(0,(int)($account['imap_last_uid']??0));
        try{$batch=(new ImapConnector())->fetchSince($account,$initialized?$lastUid:-1,10);}
        catch(\Throwable $e){$model->recordRuntimeHealth('inbound',false,(string)$e->getMessage());throw $e;}
        if(!$initialized){$model->updateCursor((int)($batch['last_uid']??0),(int)($batch['uidvalidity']??0));return;}
        $storedValidity=max(0,(int)($account['imap_uidvalidity']??0));$remoteValidity=max(0,(int)($batch['uidvalidity']??0));
        if($storedValidity>0&&$remoteValidity>0&&$storedValidity!==$remoteValidity){$fresh=(new ImapConnector())->fetchSince($account,-1,1);$model->updateCursor((int)($fresh['last_uid']??0),(int)($fresh['uidvalidity']??0));return;}
        $parser=new RawEmailParser();$cleaner=new EmailReplyCleaner();$messengerModel=new Messenger($this->registry);$channel=$messengerModel->getChannelById($channelId);$threadIndex=new EmailThreadIndex($this->registry);
        foreach($batch['messages'] as $remote){
             
             
             
             
            $uid=(int)($remote['uid']??0);$lastUid=max($lastUid,$uid);
            try{$mail=$parser->parse((string)$remote['raw']);}
            catch(\RuntimeException $e){
                $code=preg_replace('/[^a-z0-9_\-]/i','',(string)$e->getMessage())?:'email_parse_failed';
                (new MessengerLogger($this->registry,'email'))->warning('email_message_skipped',['channel_id'=>$channelId,'uid'=>$uid,'code'=>$code]);
                continue;
            }
            if($mail['from']===''||$mail['text']===''||($mail['auto_submitted']!==''&&$mail['auto_submitted']!=='no'))continue;
            $clean=$cleaner->clean($mail['text']);$thread=strtolower(trim(preg_replace('/^(?:(?:re|fw|fwd)\s*:\s*)+/i','',$mail['subject'])));if($thread==='')$thread=$mail['in_reply_to']?:$mail['message_id'];
            $references=$threadIndex->parseReferences((string)$mail['references']);if($mail['in_reply_to']!=='')$references[]=$mail['in_reply_to'];$knownChat=$threadIndex->findChat($channelId,$references);$knownContact=$knownChat>0?$messengerModel->getContactByChat($channelId,$knownChat):array();
            $recipient=$mail['reply_to']?:$mail['from'];$threadHash=hash('sha256',$mail['from'].'|'.$thread);
            $externalUserId=$knownContact?(string)$knownContact['external_user_id']:$recipient.'#ec:'.substr($threadHash,0,16);$externalChatId=$knownContact?(string)$knownContact['external_chat_id']:$threadHash;
            $incomingName=trim((string)$mail['display_name']);$storedName=trim((string)($knownContact['display_name']??''));
             
            $customerName=$incomingName!==''?$incomingName:($storedName!==''?$storedName:$mail['from']);
            $event=['external_user_id'=>$externalUserId,'external_chat_id'=>$externalChatId,'external_message_id'=>$mail['message_id']?:hash('sha256',(string)$remote['raw']),'display_name'=>$customerName,'username'=>$mail['from'],'text'=>$clean['text'],'direction'=>'in','metadata'=>['email'=>true,'customer_email'=>$mail['from'],'display_name_authority'=>$incomingName!==''?'email_header':'fallback','subject'=>$mail['subject'],'reply_to'=>$mail['reply_to'],'message_id'=>$mail['message_id'],'references'=>$references,'cleaning_confidence'=>$clean['confidence'],'quoted_text'=>$clean['quoted'],'signature_text'=>$clean['signature']]];
            $accepted=(new InboundService($this->registry))->handleWebhook('email',$channel,$event,json_encode($event,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES));
            if(!empty($accepted['chat_id'])&&$mail['message_id']!=='')$threadIndex->remember($channelId,(int)$accepted['chat_id'],(int)($accepted['message_id']??0),(string)$mail['message_id']);
        }
        $model->updateCursor($lastUid,(int)($batch['uidvalidity']??0));
        try{$model->refreshDeliverabilityIfDue();}
        catch(\Throwable $e){(new MessengerLogger($this->registry,'email'))->warning('email_deliverability_refresh_failed',['channel_id'=>$channelId,'code'=>'dns_refresh_failed']);}
    }
}
