<?php
declare(strict_types=1);

function whatsapp_config(): array {
    global $config;
    return is_array($config['whatsapp'] ?? null) ? $config['whatsapp'] : [];
}

function whatsapp_phone(string $value): string {
    $digits=preg_replace('/\D+/','',$value) ?? '';
    if(str_starts_with($digits,'00'))$digits=substr($digits,2);
    if(str_starts_with($digits,'0'))$digits='263'.substr($digits,1);
    elseif(strlen($digits)===9&&str_starts_with($digits,'7'))$digits='263'.$digits;
    return $digits;
}

function whatsapp_is_configured(): bool {
    $w=whatsapp_config();
    return !empty($w['enabled'])&&!empty($w['phone_number_id'])&&!empty($w['access_token'])&&!empty($w['verify_token'])&&!empty($w['app_secret']);
}

function whatsapp_customer_for_phone(string $phone): ?array {
    $phone=whatsapp_phone($phone);
    if($phone==='')return null;
    foreach(db()->query('SELECT id,name,company_name,phone,whatsapp FROM customers WHERE active=1 AND (phone IS NOT NULL OR whatsapp IS NOT NULL)') as $customer){
        if(whatsapp_phone((string)($customer['whatsapp']?:$customer['phone']))===$phone)return $customer;
    }
    return null;
}

function whatsapp_conversation(string $phone,?string $displayName=null): array {
    $phone=whatsapp_phone($phone);
    if($phone==='')throw new RuntimeException('A valid WhatsApp number is required.');
    $customer=whatsapp_customer_for_phone($phone);
    $stmt=db()->prepare('INSERT INTO whatsapp_conversations (customer_id,phone,display_name,last_message_at) VALUES (?,?,?,NOW()) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id),customer_id=COALESCE(customer_id,VALUES(customer_id)),display_name=COALESCE(NULLIF(VALUES(display_name),""),display_name),last_message_at=GREATEST(COALESCE(last_message_at,"1970-01-01"),VALUES(last_message_at))');
    $stmt->execute([$customer['id']??null,$phone,$displayName]);
    $id=(int)db()->lastInsertId();
    $get=db()->prepare('SELECT * FROM whatsapp_conversations WHERE id=?');$get->execute([$id]);
    return $get->fetch()?:throw new RuntimeException('WhatsApp conversation could not be created.');
}

function whatsapp_graph_request(array $payload): array {
    if(!whatsapp_is_configured())throw new RuntimeException('Level 2 is not connected to Meta yet. Ask the owner to complete WhatsApp setup.');
    $w=whatsapp_config();$version=preg_match('/^v\d+\.\d+$/',(string)($w['graph_version']??''))?$w['graph_version']:'v23.0';
    $url='https://graph.facebook.com/'.$version.'/'.rawurlencode((string)$w['phone_number_id']).'/messages';
    $ch=curl_init($url);if($ch===false)throw new RuntimeException('WhatsApp connection could not be started.');
    curl_setopt_array($ch,[CURLOPT_POST=>true,CURLOPT_RETURNTRANSFER=>true,CURLOPT_CONNECTTIMEOUT=>10,CURLOPT_TIMEOUT=>30,CURLOPT_HTTPHEADER=>['Authorization: Bearer '.$w['access_token'],'Content-Type: application/json'],CURLOPT_POSTFIELDS=>json_encode($payload,JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE)]);
    $raw=curl_exec($ch);$status=(int)curl_getinfo($ch,CURLINFO_RESPONSE_CODE);$curlError=curl_error($ch);curl_close($ch);
    if($raw===false)throw new RuntimeException('Meta connection failed: '.$curlError);
    $result=json_decode((string)$raw,true);if(!is_array($result))$result=[];
    if($status<200||$status>=300){$message=(string)($result['error']['message']??'Meta rejected the WhatsApp message.');throw new RuntimeException($message);}
    return $result;
}

function whatsapp_send(int $conversationId,string $body,?int $userId=null,?string $templateName=null,string $language='en_US',array $parameters=[]): int {
    $stmt=db()->prepare('SELECT * FROM whatsapp_conversations WHERE id=?');$stmt->execute([$conversationId]);$conversation=$stmt->fetch();
    if(!$conversation)throw new RuntimeException('WhatsApp conversation not found.');
    $body=trim($body);$payload=['messaging_product'=>'whatsapp','recipient_type'=>'individual','to'=>$conversation['phone']];
    if($templateName!==null){
        if(!preg_match('/^[a-z0-9_]+$/',$templateName))throw new RuntimeException('Enter the approved Meta template name using lowercase letters and underscores.');
        $template=['name'=>$templateName,'language'=>['code'=>$language?:'en_US']];
        if($parameters)$template['components']=[['type'=>'body','parameters'=>array_map(fn($value)=>['type'=>'text','text'=>(string)$value],$parameters)]];
        $payload['type']='template';$payload['template']=$template;$messageType='template';
    }else{
        if($body==='')throw new RuntimeException('Write a message before sending.');
        if(empty($conversation['last_customer_message_at'])||strtotime((string)$conversation['last_customer_message_at'])<time()-86400)throw new RuntimeException('The 24-hour customer service window is closed. Send an approved Meta template instead.');
        $payload['type']='text';$payload['text']=['preview_url'=>true,'body'=>substr($body,0,4096)];$messageType='text';
    }
    $result=whatsapp_graph_request($payload);$metaId=(string)($result['messages'][0]['id']??'');
    $insert=db()->prepare('INSERT INTO whatsapp_messages (conversation_id,customer_id,meta_message_id,direction,message_type,body,template_name,status,sent_by,message_at) VALUES (?,?,?,"outbound",?,?,?,"sent",?,NOW())');
    $insert->execute([$conversationId,$conversation['customer_id'],$metaId?:null,$messageType,$body?:null,$templateName,$userId]);$id=(int)db()->lastInsertId();
    db()->prepare('UPDATE whatsapp_conversations SET status="open",last_message_at=NOW() WHERE id=?')->execute([$conversationId]);
    if($conversation['customer_id']){
        db()->prepare('UPDATE customers SET last_contact_at=NOW() WHERE id=?')->execute([$conversation['customer_id']]);
        if($userId)db()->prepare('INSERT INTO crm_activities (customer_id,activity_type,subject,completed_at,notes,assigned_to,created_by) VALUES (? ,"whatsapp",?,NOW(),?,?,?)')->execute([$conversation['customer_id'],$templateName?'WhatsApp template sent':'WhatsApp reply sent',$body?:('Template: '.$templateName),$userId,$userId]);
    }
    return $id;
}

function whatsapp_webhook_signature_valid(string $raw,string $signature): bool {
    $secret=(string)(whatsapp_config()['app_secret']??'');
    if($secret===''||!str_starts_with($signature,'sha256='))return false;
    return hash_equals('sha256='.hash_hmac('sha256',$raw,$secret),$signature);
}

function whatsapp_inbound_body(array $message): string {
    $type=(string)($message['type']??'unknown');
    if($type==='text')return trim((string)($message['text']['body']??''));
    if($type==='button')return trim((string)($message['button']['text']??''));
    if($type==='interactive')return trim((string)($message['interactive']['button_reply']['title']??$message['interactive']['list_reply']['title']??'Interactive reply'));
    if($type==='location')return 'Location shared: '.($message['location']['latitude']??'').', '.($message['location']['longitude']??'');
    if($type==='contacts')return 'Contact shared';
    return '['.ucfirst($type).' received]'.(!empty($message[$type]['caption'])?' '.$message[$type]['caption']:'');
}

function whatsapp_process_webhook(array $payload): void {
    foreach(($payload['entry']??[]) as $entry)foreach(($entry['changes']??[]) as $change){
        $value=$change['value']??[];
        foreach(($value['messages']??[]) as $message){
            $phone=whatsapp_phone((string)($message['from']??''));if($phone==='')continue;
            $display=null;foreach(($value['contacts']??[]) as $contact)if(whatsapp_phone((string)($contact['wa_id']??''))===$phone){$display=(string)($contact['profile']['name']??'');break;}
            $conversation=whatsapp_conversation($phone,$display);$metaId=(string)($message['id']??'');$type=(string)($message['type']??'unknown');$body=whatsapp_inbound_body($message);$at=!empty($message['timestamp'])?date('Y-m-d H:i:s',(int)$message['timestamp']):date('Y-m-d H:i:s');
            $insert=db()->prepare('INSERT IGNORE INTO whatsapp_messages (conversation_id,customer_id,meta_message_id,direction,message_type,body,status,context_message_id,message_at) VALUES (?,?,?,"inbound",?,?,"received",?,?)');
            $insert->execute([$conversation['id'],$conversation['customer_id'],$metaId?:null,$type,$body,$message['context']['id']??null,$at]);
            if($insert->rowCount()){
                db()->prepare('UPDATE whatsapp_conversations SET status="open",unread_count=unread_count+1,last_message_at=?,last_customer_message_at=? WHERE id=?')->execute([$at,$at,$conversation['id']]);
                if($conversation['customer_id']){$systemUser=(int)db()->query("SELECT id FROM users WHERE active=1 ORDER BY FIELD(role,'owner','admin','staff'),id LIMIT 1")->fetchColumn();if($systemUser)db()->prepare('INSERT INTO crm_activities (customer_id,activity_type,subject,completed_at,notes,created_by) VALUES (? ,"whatsapp","Incoming WhatsApp message",NOW(),?,?)')->execute([$conversation['customer_id'],$body,$systemUser]);}
            }
        }
        foreach(($value['statuses']??[]) as $status){
            $metaId=(string)($status['id']??'');$state=(string)($status['status']??'');if($metaId===''||!in_array($state,['sent','delivered','read','failed'],true))continue;
            $error='';if($state==='failed')$error=(string)($status['errors'][0]['title']??$status['errors'][0]['message']??'Delivery failed');
            db()->prepare('UPDATE whatsapp_messages SET status=?,error_message=? WHERE meta_message_id=?')->execute([$state,$error?:null,$metaId]);
        }
    }
}
