<?php
// ══════════════════════════════════════════════════════════════════
//  KAP DSI — GED Boite de réception email → Google Drive
//  Appelé par cron toutes les 15 minutes
// ══════════════════════════════════════════════════════════════════
if (!defined('GED_INBOX_CLI'))     define('GED_INBOX_CLI', php_sapi_name() === 'cli' || (isset($_GET['_cron']) && $_GET['_cron'] === '1'));

require_once __DIR__ . '/kap-config.php';
if (!defined('GED_CLIENT_ID'))     define('GED_CLIENT_ID',     '657289384060-p9pjbrpafnpliu26pbn73rdkb2iio4ub.apps.googleusercontent.com');
if (!defined('GED_CLIENT_SECRET')) define('GED_CLIENT_SECRET', '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');

// ── Helpers ───────────────────────────────────────────────────────
if (!function_exists('inbox_pdo')) {
function inbox_pdo() {
    if (function_exists('db')) return db();
    static $p = null;
    if ($p) return $p;
    $p = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHARSET, DB_USER, DB_PASS, [PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC]);
    return $p;
}
}

if (!function_exists('inbox_setting')) {
function inbox_setting(string $cle): string {
    $r = inbox_pdo()->query("SELECT valeur FROM app_settings WHERE cle=".inbox_pdo()->quote($cle))->fetchColumn();
    return $r ?: '';
}
}

if (!function_exists('inbox_log')) {
function inbox_log(string $msg, string $level='info'): void {
    $ts = date('Y-m-d H:i:s');
    try {
        inbox_pdo()->prepare("INSERT INTO ged_inbox_log (id,level,message,created_at) VALUES (UUID(),?,?,NOW())")
            ->execute([$level, $msg]);
    } catch(Exception $e) {}
    if (GED_INBOX_CLI) echo "[$ts][$level] $msg\n";
}
}

if (!function_exists('inbox_drive_token')) {
function inbox_drive_token(): string {
    $cache = inbox_pdo()->query("SELECT valeur FROM app_settings WHERE cle='ged_access_token'")->fetchColumn();
    if ($cache) {
        $d = json_decode($cache, true);
        if (!empty($d['access_token']) && ($d['expires_at']??0) > time()+60)
            return $d['access_token'];
    }
    $rt = inbox_setting('ged_refresh_token');
    if (!$rt) throw new Exception('Refresh token Drive manquant');
    $ch = curl_init('https://oauth2.googleapis.com/token');
    curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_POST=>true,
        CURLOPT_POSTFIELDS=>http_build_query(['client_id'=>GED_CLIENT_ID,'client_secret'=>GED_CLIENT_SECRET,'refresh_token'=>$rt,'grant_type'=>'refresh_token']),
        CURLOPT_HTTPHEADER=>['Content-Type: application/x-www-form-urlencoded']]);
    $res = curl_exec($ch); curl_close($ch);
    $d = json_decode($res, true);
    if (empty($d['access_token'])) throw new Exception('Token Drive invalide: '.$res);
    $d['expires_at'] = time() + ($d['expires_in']??3600) - 60;
    inbox_pdo()->prepare("INSERT INTO app_settings (cle,valeur,label,description) VALUES ('ged_access_token',?,'GED','') ON DUPLICATE KEY UPDATE valeur=?")
        ->execute([json_encode($d), json_encode($d)]);
    return $d['access_token'];
}
}

if (!function_exists('inbox_drive_upload')) {
function inbox_drive_upload(string $token, string $filename, string $content, string $mimeType, string $folderId): array {
    $meta = json_encode(['name'=>$filename, 'parents'=>[$folderId]]);
    $boundary = '----GEDInboxBoundary'.uniqid();
    $body = "--$boundary\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n$meta\r\n"
           ."--$boundary\r\nContent-Type: $mimeType\r\nContent-Transfer-Encoding: base64\r\n\r\n".base64_encode($content)."\r\n"
           ."--$boundary--";
    $ch = curl_init('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&supportsAllDrives=true&fields=id,name,size,mimeType');
    curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>$body,
        CURLOPT_HTTPHEADER=>["Authorization: Bearer $token","Content-Type: multipart/related; boundary=$boundary"]]);
    $res = json_decode(curl_exec($ch), true); curl_close($ch);
    if (empty($res['id'])) throw new Exception('Upload Drive failed: '.json_encode($res));
    return $res;
}
}

if (!function_exists('inbox_find_or_create_folder')) {
function inbox_find_or_create_folder(string $token, string $name, string $parentId): string {
    $q = urlencode("name='$name' and mimeType='application/vnd.google-apps.folder' and '$parentId' in parents and trashed=false");
    $ch = curl_init("https://www.googleapis.com/drive/v3/files?q=$q&supportsAllDrives=true&includeItemsFromAllDrives=true&fields=files(id)");
    curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_HTTPHEADER=>["Authorization: Bearer $token"]]);
    $res = json_decode(curl_exec($ch), true); curl_close($ch);
    if (!empty($res['files'][0]['id'])) return $res['files'][0]['id'];
    $ch2 = curl_init('https://www.googleapis.com/drive/v3/files?supportsAllDrives=true&fields=id');
    curl_setopt_array($ch2, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_POST=>true,
        CURLOPT_POSTFIELDS=>json_encode(['name'=>$name,'mimeType'=>'application/vnd.google-apps.folder','parents'=>[$parentId]]),
        CURLOPT_HTTPHEADER=>["Authorization: Bearer $token","Content-Type: application/json"]]);
    $res2 = json_decode(curl_exec($ch2), true); curl_close($ch2);
    if (empty($res2['id'])) throw new Exception('Impossible de créer le dossier: '.$name);
    return $res2['id'];
}
}

// ── Extensions acceptées ──────────────────────────────────────────
$ALLOWED_EXTS = ['pdf','doc','docx','xls','xlsx','ppt','pptx','odt','ods','odp','txt','csv','png','jpg','jpeg','gif','webp','zip'];

// ── Main ──────────────────────────────────────────────────────────
try {
    $imapHost   = inbox_setting('ged_inbox_imap_host')   ?: 'mail.td-info.fr';
    $imapPort   = inbox_setting('ged_inbox_imap_port')   ?: '993';
    $imapUser   = inbox_setting('ged_inbox_imap_user')   ?: 'gedkapdsi@td-info.fr';
    $imapPass   = inbox_setting('ged_inbox_imap_pass')   ?: '';
    $rootFolder = inbox_setting('ged_root_folder_id');
    $inboxName  = inbox_setting('ged_inbox_folder_name') ?: 'Boite de reception';

    if (!$imapPass) { inbox_log('Mot de passe IMAP non configuré','error'); if(GED_INBOX_CLI) exit(1); return; }
    if (!$rootFolder) { inbox_log('Dossier racine GED non configuré','error'); if(GED_INBOX_CLI) exit(1); return; }

    // Connexion IMAP
    $mailbox = "{{$imapHost}:{$imapPort}/imap/ssl/novalidate-cert}INBOX";
    $imap = imap_open($mailbox, $imapUser, $imapPass);
    if (!$imap) {
        inbox_log('Connexion IMAP échouée: '.imap_last_error(),'error');
        if(GED_INBOX_CLI) exit(1); return;
    }
    inbox_log("Connexion IMAP OK ($imapUser)");

    // Emails non lus
    $emails = imap_search($imap, 'UNSEEN');
    if (!$emails) {
        inbox_log('Aucun email non lu'); imap_close($imap); if(GED_INBOX_CLI) exit(0); return;
    }

    inbox_log(count($emails).' email(s) à traiter');
    $driveToken = inbox_drive_token();

    // Trouver/créer le dossier "Boite de reception" sur Drive
    $inboxFolderId = inbox_find_or_create_folder($driveToken, $inboxName, $rootFolder);
    // Mémoriser l'ID pour que le Hub puisse détecter la navigation vers ce dossier
    inbox_pdo()->prepare("INSERT INTO app_settings (cle,valeur,label,description) VALUES ('ged_inbox_folder_id',?,'GED','') ON DUPLICATE KEY UPDATE valeur=?")
        ->execute([$inboxFolderId, $inboxFolderId]);

    $imported = 0;
    foreach ($emails as $msgId) {
        $header = imap_headerinfo($imap, $msgId);
        $subject = isset($header->subject) ? imap_utf8($header->subject) : '(sans objet)';
        $from    = isset($header->from[0]) ? ($header->from[0]->mailbox.'@'.$header->from[0]->host) : 'inconnu';
        inbox_log("Email: \"$subject\" de $from");

        $structure = imap_fetchstructure($imap, $msgId);
        $parts = isset($structure->parts) ? $structure->parts : [$structure];
        $attachments = [];

        // Parcourir les parties
        $inbox_scan_parts = function($parts, $prefix='') use (&$inbox_scan_parts, $imap, $msgId, &$attachments, $ALLOWED_EXTS) {
            foreach ($parts as $i => $part) {
                $partNum = $prefix ? $prefix.'.'.($i+1) : (string)($i+1);
                $filename = '';
                if (!empty($part->dparameters)) {
                    foreach ($part->dparameters as $dp) {
                        if (strtolower($dp->attribute) === 'filename') $filename = imap_utf8($dp->value);
                    }
                }
                if (!$filename && !empty($part->parameters)) {
                    foreach ($part->parameters as $p) {
                        if (strtolower($p->attribute) === 'name') $filename = imap_utf8($p->value);
                    }
                }
                if ($filename) {
                    $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
                    if (in_array($ext, $ALLOWED_EXTS)) {
                        $encoding = $part->encoding;
                        $data = imap_fetchbody($imap, $msgId, $partNum);
                        if ($encoding == 3) $data = base64_decode($data);
                        elseif ($encoding == 4) $data = quoted_printable_decode($data);
                        $typeMap = [0=>'text',1=>'multipart',2=>'message',3=>'application',4=>'audio',5=>'image',6=>'video',7=>'other'];
                        $mimeType = ($typeMap[$part->type]??'application').'/'.strtolower($part->subtype);
                        $attachments[] = ['filename'=>$filename,'data'=>$data,'mime'=>$mimeType];
                    }
                }
                if (!empty($part->parts)) $inbox_scan_parts($part->parts, $partNum);
            }
        };
        $inbox_scan_parts($parts);

        if (empty($attachments)) {
            inbox_log("  → Aucune pièce jointe valide");
            imap_setflag_full($imap, (string)$msgId, '\\Seen');
            continue;
        }

        foreach ($attachments as $att) {
            try {
                $file = inbox_drive_upload($driveToken, $att['filename'], $att['data'], $att['mime'], $inboxFolderId);
                // Enregistrer dans ged_fichiers
                $fichierId = bin2hex(random_bytes(16)); // UUID simplifié
                inbox_pdo()->prepare("INSERT INTO ged_fichiers (id,drive_file_id,dossier_id,nom_affichage,date_creation) VALUES (?,?,?,?,NOW())")
                    ->execute([$fichierId, $file['id'], $inboxFolderId, $att['filename']]);
                // Enregistrer la version avec mime_type
                inbox_pdo()->prepare("INSERT INTO ged_versions (id,fichier_id,drive_file_id,version,nom_original,taille,mime_type,date_upload) VALUES (UUID(),?,?,1,?,?,?,NOW())")
                    ->execute([$fichierId, $file['id'], $att['filename'], $file['size']??0, $att['mime']]);
                inbox_log("  → Importé: {$att['filename']} ({$file['id']})");
                $imported++;
            } catch(Exception $e) {
                inbox_log("  → Erreur upload {$att['filename']}: ".$e->getMessage(),'error');
            }
        }
        imap_setflag_full($imap, (string)$msgId, '\\Seen');
    }

    imap_close($imap);
    inbox_log("Terminé: $imported fichier(s) importé(s)");

    // Mettre à jour le compteur pour le badge Hub
    inbox_pdo()->prepare("INSERT INTO app_settings (cle,valeur,label,description) VALUES ('ged_inbox_new_count',?,'Badge GED','') ON DUPLICATE KEY UPDATE valeur=valeur+?")
        ->execute([$imported, $imported]);

} catch(Exception $e) {
    inbox_log('Erreur fatale: '.$e->getMessage(),'error');
    if(GED_INBOX_CLI) exit(1);
}
