<?php
/**
 * presence.php — Mesai içi (09:00–18:30, Pzt–Cum) >=15 dk offline uyarı + WhatsApp mesaj
 * ve günlük/haftalık/aylık raporları Telegram'a yollar.
 *
 * PHP 7.0+
 *
 * Modlar:
 *   php presence.php scan
 *   php presence.php daily
 *   php presence.php weekly
 *   php presence.php monthly
 */

date_default_timezone_set('Europe/Istanbul');

/* ================== AYARLAR ================== */

define('DATA_DIR', __DIR__ . '/data');                         // JSONL klasörü
define('ALERT_LOCK_FILE', DATA_DIR . '/alert_lock.json');      // Telegram uyarı tekrarını engelle
define('SEND_LOCK_FILE',  DATA_DIR . '/send_lock.json');       // WhatsApp mesaj tekrarını engelle
define('SECRET_TOKEN', 'BURAYA_GUVENLI_BIR_TOKEN');            // (Sadece web tetikleme istersen)

define('MIN_ALERT_MIN', 15);                                   // 15 dk eşiği
define('MIN_ALERT_SEC', MIN_ALERT_MIN * 60);                   // saniye

define('WORK_START_H', 9);
define('WORK_START_M', 0);
define('WORK_END_H',   18);  // 8 değil 18
define('WORK_END_M',   30);
define('WORK_DAYS', '1,2,3,4,5,6'); // hafta içi



// Maytapi (kendi değerlerinizi yazın)
$PRODUCT_ID = '396f5410-b88a-475a-888a-45e17f7e1850';
$PHONE_ID   = '92917';
$API_KEY    = '2fcccc11-1f79-49a1-933c-1e0b93681f04';

// Telegram (kendi değerlerinizi yazın)
$TG_BOT   = '8169151763:AAFcK8U9s_Y83yMalfawMlE_D0QE4HN1ons';
$TG_CHAT  = '-1002970799174';  // süpergrup id
$TG_TOPIC = null;              // topic id (varsa)

// İzleme listesi (msisdn => meta)

$WATCHLIST = array(
  '905356649536' => array('name' => 'Feray'),
  '905423212512' => array('name' => 'Meriç'),
  '905491293455' => array('name' => 'Sam'),
  '905445278625' => array('name' => 'Hayat Bener'),
  '905071978381' => array('name' => 'Fatma'),
  '905456771445' => array('name' => 'Planning'),
  '353852388085' => array('name' => 'Tugay'),
  '905456723625' => array('name' => 'Emre'),
  '905456771431' => array('name' => 'Recep'),
  '905423697465' => array('name' => 'Morris'),
  '905356649539' => array('name' => 'Oksana'),
  '905456773182' => array('name' => 'Ahmet'),
  '905465240867' => array('name' => 'Hanin'),
  '905433442905' => array('name' => 'Mina'),
  '905423697491' => array('name' => 'Daniela'),
  '905456744780' => array('name' => 'Naz'),
  '905421333283' => array('name' => 'Amra'),
  '905456771452' => array('name' => 'Ayca'),
  '905465241282' => array('name' => 'Ramez'),
  '905423697481' => array('name' => 'Madina'),
  '905466560262' => array('name' => 'Nazar'),
  '905467631686' => array('name' => 'Talha'),
  '905467631689' => array('name' => 'Erdi'),
);


// WhatsApp mesaj içeriği (kişiye gider)
define('WA_MESSAGE_TEXT', "Hey [name], it looks like you’ve been offline for 15+ minutes during working hours. Could you hop back on WhatsApp? — Hosfinder");
define('WA_MESSAGE_MEDIA_URL', "http://hoscreative.com/wp-content/uploads/2025/09/outer-space.jpg"); // örn: "http://placehold.it/180" — boşsa sadece metin gönderilir

/* ================== YARDIMCI FONKSİYONLAR ================== */

if (!is_dir(DATA_DIR)) { @mkdir(DATA_DIR, 0775, true); }

function dayfile(DateTime $dt) { return DATA_DIR . '/presence_' . $dt->format('Y-m-d') . '.jsonl'; }

function jsonl_append($file, $row) {
  $fh = fopen($file, 'ab'); if (!$fh) return;
  if (flock($fh, LOCK_EX)) {
    fwrite($fh, json_encode($row, JSON_UNESCAPED_UNICODE) . "\n");
    fflush($fh); flock($fh, LOCK_UN);
  }
  fclose($fh);
}

function normalize_msisdn($msisdn) { return (string)preg_replace('/\D+/', '', (string)$msisdn); }

/** Mesai içi mi? Pzt–Cum ve 09:00–18:30 arası */
function is_business_hours(DateTime $dt): bool {
  $dow = (int)$dt->format('N'); // 1..7
  if (!in_array($dow, array_map('intval', explode(',', WORK_DAYS)), true)) return false;
  $t   = (int)$dt->format('Hi'); // HHMM
  $start = WORK_START_H*100 + WORK_START_M; // 900
  $end   = WORK_END_H*100   + WORK_END_M;   // 1830
  return ($t >= $start && $t <= $end);
}

/** Maytapi presence çağrısı */
function maytapi_get_presence($productId, $phoneId, $apiKey, $msisdn) {
  $msisdn = normalize_msisdn($msisdn); if ($msisdn === '') return null;
  $chatId = $msisdn . '@c.us';
  $url = "https://api.maytapi.com/api/{$productId}/{$phoneId}/getPresences/{$chatId}";
  $ch = curl_init($url);
  curl_setopt_array($ch, array(
    CURLOPT_HTTPHEADER     => array('accept: application/json', 'x-maytapi-key: ' . $apiKey),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 20
  ));
  $res = curl_exec($ch); if ($res === false) { curl_close($ch); return null; }
  curl_close($ch);
  $j = json_decode($res, true);
  if (!is_array($j) || empty($j['success'])) return null;
  return $j['data'] ?? null; // ['chatId','last_seen','status']
}

/** last_seen epoch → DateTime & farklar */
function safe_last_seen_to_dt($epochRaw, DateTime $now) {
  if ($epochRaw === null || $epochRaw === '' || $epochRaw === false) return array(null, null, null);
  if (!is_numeric($epochRaw)) return array(null, null, null);
  $e = (int)$epochRaw; if ($e > 2000000000) $e = (int)floor($e/1000);
  $minOk=1104537600; $maxOk=4102444800; if ($e<$minOk||$e>$maxOk) return array(null,null,null);
  $last = new DateTime('@'.$e); $last->setTimezone($now->getTimezone());
  $diffSec = max(0, $now->getTimestamp() - $last->getTimestamp());
  $diffMin = (int) floor($diffSec/60);
  return array($last, $diffMin, $diffSec);
}

/** Telegram gönder — topic'li/topicsiz dene, hatayı döndür */
function tg_send($botToken, $chatId, $topicId, $text, &$errors = null) {
  $url = "https://api.telegram.org/bot{$botToken}/sendMessage";
  $base = array('chat_id'=>$chatId,'text'=>$text,'parse_mode'=>'HTML','disable_web_page_preview'=>true);
  $tries = [];
  if (!empty($topicId)) { $p = $base; $p['message_thread_id']=$topicId; $tries[]=$p; }
  $tries[]=$base;

  foreach ($tries as $pl) {
    $ch = curl_init($url);
    curl_setopt_array($ch, array(CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>$pl, CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>20));
    $res=curl_exec($ch); $http=curl_getinfo($ch, CURLINFO_HTTP_CODE); $err=curl_error($ch); curl_close($ch);
    if ($res!==false && $http===200) { $j=json_decode($res,true); if (($j['ok']??false)===true) return true; }
    if ($errors!==null) $errors[]=['http'=>$http,'curl'=>$err,'resp'=>$res,'payload'=>$pl];
  }
  return false;
}

/** WhatsApp mesaj gönderimi (Maytapi sendMessage) */
function maytapi_send_whatsapp($productId,$phoneId,$apiKey,$toMsisdn,$text,$mediaUrl='') {
  $to = '+' . normalize_msisdn($toMsisdn);
  $url = "https://api.maytapi.com/api/{$productId}/{$phoneId}/sendMessage";
  $payload = ["to_number"=>$to];
  if ($mediaUrl) { $payload["type"]="media"; $payload["message"]=$mediaUrl; $payload["text"]=(string)$text; }
  else { $payload["type"]="text"; $payload["message"]=(string)$text; }

  $ch=curl_init($url);
  curl_setopt_array($ch, array(
    CURLOPT_HTTPHEADER=>array('Content-Type: application/json','x-maytapi-key: '.$apiKey),
    CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode($payload, JSON_UNESCAPED_UNICODE),
    CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>20
  ));
  $res=curl_exec($ch); $http=curl_getinfo($ch,CURLINFO_HTTP_CODE); $err=curl_error($ch); curl_close($ch);
  $ok=($res!==false && $http>=200 && $http<300);
  return array($ok,$http,$err,$res,$payload);
}

/** Lock dosyaları */
function load_lock($file){ if(!is_file($file))return[]; $j=json_decode(@file_get_contents($file),true); return is_array($j)?$j:[]; }
function save_lock($file,$data){ @file_put_contents($file,json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT)); }

/* ================== SCAN (mesai içi 15+ dk offline) ================== */
function do_scan($PRODUCT_ID,$PHONE_ID,$API_KEY,$TG_BOT,$TG_CHAT,$TG_TOPIC,$WATCHLIST){
  $now=new DateTime();
  $file=dayfile($now);
  $alerts=[]; // telegram satırları
  $alertLock=load_lock(ALERT_LOCK_FILE);
  $sendLock =load_lock(SEND_LOCK_FILE);

  $businessNow = is_business_hours($now);

  foreach($WATCHLIST as $msisdnKey=>$meta){
    $msisdn=normalize_msisdn((string)$msisdnKey);
    $name  =$meta['name'] ?? $msisdn;

    $data=maytapi_get_presence($PRODUCT_ID,$PHONE_ID,$API_KEY,$msisdn);
    if(!$data){
      jsonl_append($file, ['ts'=>$now->format(DateTime::ATOM),'msisdn'=>$msisdn,'name'=>$name,'status'=>'unknown','last_seen'=>null,'diff_min'=>null,'diff_sec'=>null,'note'=>'maytapi_fail']);
      continue;
    }

    $status=$data['status'] ?? 'unknown';
    $epoch =$data['last_seen'] ?? null;
    list($lastDt,$diffMin,$diffSec)=safe_last_seen_to_dt($epoch,$now);
    $lastIso=$lastDt?$lastDt->format(DateTime::ATOM):null;

    // ham log
    jsonl_append($file, ['ts'=>$now->format(DateTime::ATOM),'msisdn'=>$msisdn,'name'=>$name,'status'=>$status,'last_seen'=>$lastIso,'diff_min'=>$diffMin,'diff_sec'=>$diffSec]);

    // Mesai dışında asla mesaj/uyarı gönderme
    if(!$businessNow) continue;

    // Kural: offline && last_seen geçerli && diff_sec >= 15 dk
    if($status!=='online' && $lastDt){
      $ds = ($diffSec!==null)?$diffSec:($now->getTimestamp()-$lastDt->getTimestamp());
      if($ds >= MIN_ALERT_SEC){
        $clock=$lastDt->format('H:i');
        $lockKey=$msisdn; $seenKey=$lastIso?:'null';

        // 1) Telegram uyarısı (aynı last_seen için bir kez)
        if(!isset($alertLock[$lockKey]) || $alertLock[$lockKey]!==$seenKey){
          $alerts[]="• {$name}: son görülme {$diffMin} dk önce ({$clock}) — mesai içinde 15+ dk offline";
          $alertLock[$lockKey]=$seenKey;

          // raporlama için özel "alert" kaydı
          jsonl_append($file, [
            'ts'=>$now->format(DateTime::ATOM),
            'msisdn'=>$msisdn,
            'name'=>$name,
            'action'=>'alert',
            'offline_min_at_alert'=>$diffMin,
            'last_seen'=>$lastIso,
            'business_hours'=>true
          ]);
        }

        // 2) WhatsApp mesaj (aynı last_seen için bir kez); cooldown ekleyebilirsiniz (gerekirse)
        $sendInfo=$sendLock[$msisdn] ?? [];
        $lastSeenSent=$sendInfo['last_seen_iso'] ?? null;

        if($lastSeenSent !== $seenKey){
          $txt=str_replace('[name]',$name, WA_MESSAGE_TEXT);
          $media=WA_MESSAGE_MEDIA_URL;

          list($ok,$http,$cerr,$resp,$payload)=maytapi_send_whatsapp($PRODUCT_ID,$PHONE_ID,$API_KEY,$msisdn,$txt,$media);

          $sendLock[$msisdn]=['last_seen_iso'=>$seenKey,'last_sent_iso'=>$now->format(DateTime::ATOM),'http'=>$http,'resp'=>$resp];

          jsonl_append($file, [
            'ts'=>$now->format(DateTime::ATOM),
            'msisdn'=>$msisdn,
            'name'=>$name,
            'action'=>'whatsapp_send',
            'ok'=>$ok,'http'=>$http,'resp'=>$resp,'payload'=>$payload
          ]);
        }
      }
    }

    usleep(150000);
  }

  save_lock(ALERT_LOCK_FILE,$alertLock);
  save_lock(SEND_LOCK_FILE,$sendLock);

  if(!empty($alerts)){
    $msg="⚠️ Mesai içi 15+ dk offline uyarıları\n".implode("\n",$alerts);
    $errs=[]; tg_send($GLOBALS['TG_BOT'],$GLOBALS['TG_CHAT'],$GLOBALS['TG_TOPIC'],$msg,$errs);
    // hata varsa istersen logla: file_put_contents(DATA_DIR.'/tg_err_'.date('Ymd_His').'.log', print_r($errs,true));
  }
}

/* ================== RAPORLAMA (daily/weekly/monthly) ================== */

function analyze_range(DateTime $start, DateTime $end, array $watchlist): array {
  $stats=[];
  foreach($watchlist as $msisdn=>$meta){
    $stats[$msisdn]=[
      'name'=>$meta['name']??$msisdn,
      'events'=>0,               // kaç alert
      'total_offline_min'=>0,    // alert anındaki diff_min toplamı
      'max_offline_min'=>0       // en uzun alert anı
    ];
  }

  $cur=clone $start;
  while($cur <= $end){
    $file=dayfile($cur);
    if(is_file($file)){
      $fh=fopen($file,'rb');
      while(($line=fgets($fh))!==false){
        $row=json_decode(trim($line),true); if(!$row) continue;

        // tarih aralığı
        $tsStr=$row['ts'] ?? null; if(!$tsStr) continue;
        $ts=new DateTime($tsStr);
        if($ts < $start || $ts > $end) continue;

        $msisdn=$row['msisdn'] ?? null; if(!$msisdn || !isset($stats[$msisdn])) continue;

        // sadece "alert" action'larını say (mesai içi)
        if(($row['action'] ?? '') === 'alert' && ($row['business_hours'] ?? false)){
          $min = (int)($row['offline_min_at_alert'] ?? 0);
          $stats[$msisdn]['events']++;
          $stats[$msisdn]['total_offline_min'] += $min;
          if($min > $stats[$msisdn]['max_offline_min']) $stats[$msisdn]['max_offline_min']=$min;
        }
      }
      fclose($fh);
    }
    $cur->modify('+1 day');
  }

  // sıralama: çok olay → toplam süre → maksimum süre
  uasort($stats, function($a,$b){
    if($a['events'] === $b['events']){
      if($a['total_offline_min'] === $b['total_offline_min']){
        return $b['max_offline_min'] <=> $a['max_offline_min'];
      }
      return $b['total_offline_min'] <=> $a['total_offline_min'];
    }
    return $b['events'] <=> $a['events'];
  });

  return $stats;
}

function send_report($title, array $stats){
  $lines=["{$title}","(Mesai: Pzt–Cum, 09:00–18:30, eşik: ".MIN_ALERT_MIN." dk)\n"];
  $empty=true;
  foreach($stats as $msisdn=>$s){
    if($s['events']>0){
      $empty=false;
      $lines[] = sprintf("• %s (%s): %d kez, toplam %d dk (maks %d dk)",
        $s['name'],$msisdn,$s['events'],$s['total_offline_min'],$s['max_offline_min']);
    }
  }
  if($empty){ $lines[]="Kayıtlı ihlal yok."; }
  $msg=implode("\n",$lines);
  $errs=[]; tg_send($GLOBALS['TG_BOT'],$GLOBALS['TG_CHAT'],$GLOBALS['TG_TOPIC'],$msg,$errs);
}

/* ================== GİRİŞ & ÇALIŞTIRMA ================== */

$MODE = $argv[1] ?? ($_GET['mode'] ?? 'scan'); // scan|daily|weekly|monthly

if (php_sapi_name() !== 'cli') {
  $token = $_GET['token'] ?? '';
  if ($token !== SECRET_TOKEN) { http_response_code(401); header('Content-Type: text/plain'); echo "401 Unauthorized\n"; exit; }
}

switch ($MODE) {
  case 'scan':
    do_scan($PRODUCT_ID,$PHONE_ID,$API_KEY,$TG_BOT,$TG_CHAT,$TG_TOPIC,$WATCHLIST);
    if (php_sapi_name() !== 'cli') { header('Content-Type: text/plain; charset=utf-8'); echo "Scan OK\n"; }
    break;

  case 'daily': {
    $now=new DateTime();
    $start=(clone $now)->setTime(0,0,0);
    $stats=analyze_range($start,$now,$WATCHLIST);
    $title="📊 Günlük Rapor (".$start->format('Y-m-d').")";
    send_report($title,$stats);
    if (php_sapi_name() !== 'cli') { header('Content-Type: text/plain; charset=utf-8'); echo "Daily report sent.\n"; }
    break;
  }

  case 'weekly': {
    $now=new DateTime();
    $dow=(int)$now->format('N'); // Pazartesi=1
    $start=(clone $now)->modify('-'.($dow-1).' days')->setTime(0,0,0);
    $stats=analyze_range($start,$now,$WATCHLIST);
    $title="📈 Haftalık Rapor (".$start->format('Y-m-d')." → ".$now->format('Y-m-d').")";
    send_report($title,$stats);
    if (php_sapi_name() !== 'cli') { header('Content-Type: text/plain; charset=utf-8'); echo "Weekly report sent.\n"; }
    break;
  }

  case 'monthly': {
    $now=new DateTime();
    $start=(clone $now)->modify('first day of this month')->setTime(0,0,0);
    $stats=analyze_range($start,$now,$WATCHLIST);
    $title="📈 Aylık Rapor (".$now->format('Y-m').")";
    send_report($title,$stats);
    if (php_sapi_name() !== 'cli') { header('Content-Type: text/plain; charset=utf-8'); echo "Monthly report sent.\n"; }
    break;
  }

  default:
    if (php_sapi_name() !== 'cli') { header('Content-Type: text/plain; charset=utf-8'); }
    echo "Kullanım: php presence.php [scan|daily|weekly|monthly]\n";
}
