<?php
// ECUPRATIX DTC MODULE API (embedded) - no separate login
// Actions:
// - user_upload (POST file: user_bin)
// - user_patch  (POST token + rows[])
// - user_status (optional)

if (session_status() === PHP_SESSION_NONE) { session_start(); }

header('Content-Type: application/json; charset=utf-8');

// Require ECUPRATIX auth (same session)
if (!isset($_SESSION['auth'])) {
  echo json_encode(["status"=>"error","msg"=>"unauthorized"]); exit;
}

@ini_set('memory_limit', '1024M');
@ini_set('upload_max_filesize', '512M');
@ini_set('post_max_size', '512M');
@ini_set('max_execution_time', '300');

$BASE = __DIR__;
$tempDir = $BASE . '/temp';
if (!file_exists($tempDir)) { @mkdir($tempDir, 0777, true); }

require_once $BASE . '/EcuEngine.php';

function _upload_err_msg($code) {
  $map = [
    UPLOAD_ERR_OK => 'OK',
    UPLOAD_ERR_INI_SIZE => 'Dosya sunucu limitini aştı (upload_max_filesize).',
    UPLOAD_ERR_FORM_SIZE => 'Dosya form limitini aştı (MAX_FILE_SIZE).',
    UPLOAD_ERR_PARTIAL => 'Dosya kısmi yüklendi.',
    UPLOAD_ERR_NO_FILE => 'Dosya seçilmedi.',
    UPLOAD_ERR_NO_TMP_DIR => 'TMP klasörü yok.',
    UPLOAD_ERR_CANT_WRITE => 'Disk yazma hatası.',
    UPLOAD_ERR_EXTENSION => 'PHP uzantı hatası.',
  ];
  return $map[$code] ?? ('Upload error: ' . $code);
}

function _require_upload($field) {
  global $tempDir;
  if (!isset($_FILES[$field])) return [false, "Dosya yok ($field)"];
  $f = $_FILES[$field];
  if (($f['error'] ?? UPLOAD_ERR_OK) !== UPLOAD_ERR_OK) return [false, _upload_err_msg($f['error'])];
  if (!is_uploaded_file($f['tmp_name'])) return [false, "Upload tmp invalid"];
  $name = basename($f['name'] ?? 'file.bin');
  $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
  if (!in_array($ext, ['bin','ori','dat','frf','sgo','mod'])) return [false, "Desteklenmeyen uzantı: .$ext"];
  $dst = $tempDir . '/' . md5(uniqid('', true)) . '.' . $ext;
  if (!@move_uploaded_file($f['tmp_name'], $dst)) return [false, "Dosya taşınamadı"];
  return [true, $dst, $name];
}

function _fs_profile_path(string $rel): string {
  $rel = ltrim($rel, '/');
  if (strpos($rel, 'dtcpatcher/') === 0) $rel = substr($rel, strlen('dtcpatcher/'));
  return dirname(__DIR__) . '/dtc_module/' . $rel;
}

$action = $_POST['action'] ?? '';
$engine = new EcuEngine();

// ---- USER UPLOAD: strict SIM/ADDR gate ----
if ($action === 'user_upload') {
  list($okU,$binPath,$origName) = _require_upload('user_bin');
  if(!$okU){ echo json_encode(['status'=>'error','msg'=>$binPath]); exit; }

  $binData = @file_get_contents($binPath);
  if($binData === false || $binData === ''){ echo json_encode(['status'=>'error','msg'=>'Binary okunamadı']); exit; }

  $MIN_SIM  = 60.0;
  $MIN_ADDR = 70.0;

  $profiles = [];
  $pPath = $BASE . '/profiles_db.json';
  if (file_exists($pPath)) $profiles = json_decode(file_get_contents($pPath), true);
  if (!is_array($profiles)) $profiles = [];

  $best = null;

  foreach ($profiles as $idx => $p) {
    $sim = 0.0;
    if (!empty($p['master_bin_path'])) {
      $masterFs = _fs_profile_path((string)$p['master_bin_path']);
      if (file_exists($masterFs)) {
        $tmpSim = $engine->bytewiseSimilarityFile($masterFs, $binPath);
        if ($tmpSim !== null) $sim = floatval($tmpSim);
      }
    }
    if ($sim < $MIN_SIM) continue;

    $jsonMap = json_decode($p['json_text'] ?? '', true);
    if (!is_array($jsonMap)) continue;

    $maps = $engine->getMaps($jsonMap);
    $addrScore = $engine->signatureMatchScore($binData, $maps, $p['map_signatures'] ?? []);
    if ($addrScore < $MIN_ADDR) continue;

    $row = ['idx'=>$idx,'profile'=>$p,'similarity'=>$sim,'addr_score'=>$addrScore];
    if ($best === null) $best = $row;
    else {
      if ($row['similarity'] > $best['similarity']) $best = $row;
      else if ($row['similarity'] == $best['similarity'] && $row['addr_score'] > $best['addr_score']) $best = $row;
    }
  }

  if ($best === null) {
    echo json_encode(['status'=>'error','msg'=>'Tablo bulunamadı (SIM<60 veya ADDR<70)','sim_min'=>$MIN_SIM,'addr_min'=>$MIN_ADDR]);
    exit;
  }

  $profile = $best['profile'];
  $token = md5(uniqid('', true));

  // keep uploaded bin
  @file_put_contents($tempDir . "/{$token}.bin", $binData);
  @file_put_contents($tempDir . "/{$token}_profile.json", json_encode($profile, JSON_UNESCAPED_UNICODE));

  $jsonMap = json_decode($profile['json_text'], true);
  $maps = $engine->getMaps($jsonMap);

  foreach ($maps as &$m) {
    $origStart = $engine->parseAddr($m['Fieldvalues.StartAddr'] ?? $m['StartAddr'] ?? $m['start'] ?? '$0');
    $m['detected_addr'] = $origStart;
  }
  @file_put_contents($tempDir . "/{$token}_maps.json", json_encode($maps, JSON_UNESCAPED_UNICODE));

  $results = [];
  $methods = $profile['read_methods'] ?? [];
  $tables  = $profile['read_tables'] ?? [];
  if (is_string($methods)) { $tmp = json_decode($methods, true); if (is_array($tmp)) $methods = $tmp; }
  if (is_string($tables))  { $tmp = json_decode($tables, true); if (is_array($tmp)) $tables  = $tmp; }

  if (is_array($methods)) {
    foreach ($methods as $method) {
      $res = $engine->executeMethod($method, $binData, $maps, $tables);
      if (is_array($res)) $results = array_merge($results, $res);
    }
  }

  echo json_encode([
    'status'=>'ok',
    'token'=>$token,
    'profile_name'=>($profile['name'] ?? ''),
    'align_msg'=>"SIM:" . number_format($best['similarity'],2) . "% | ADDR:" . number_format($best['addr_score'],2) . "%",
    'similarity'=>$best['similarity'],
    'addr_score'=>$best['addr_score'],
    'brand'=>($profile['brand'] ?? ''),
    'ecu_model'=>($profile['ecu_model'] ?? ''),
    'brand_group'=>($profile['brand_group'] ?? ''),
    'brand_logo'=>($profile['brand_logo'] ?? ''),
    'data'=>$results
  ], JSON_UNESCAPED_UNICODE);
  exit;
}

// ---- USER PATCH ----
if ($action === 'user_patch') {
  $token = $_POST['token'] ?? '';
  if ($token === '') { echo json_encode(['status'=>'error','msg'=>'Token yok']); exit; }

  $rows = $_POST['rows'] ?? null;
  if ($rows === null) { echo json_encode(['status'=>'error','msg'=>'Seçim yapılmadı']); exit; }
  $selectedRows = is_array($rows) ? $rows : explode(',', (string)$rows);

  $binFile = $tempDir . "/{$token}.bin";
  if (!file_exists($binFile)) { echo json_encode(['status'=>'error','msg'=>'Timeout (upload tekrar)']); exit; }
  $binData = file_get_contents($binFile);

  $mapsFile = $tempDir . "/{$token}_maps.json";
  $profileFile = $tempDir . "/{$token}_profile.json";
  $maps = file_exists($mapsFile) ? json_decode(file_get_contents($mapsFile), true) : null;
  $profile = file_exists($profileFile) ? json_decode(file_get_contents($profileFile), true) : null;

  if (!is_array($profile)) { echo json_encode(['status'=>'error','msg'=>'Profil bulunamadı (upload tekrar)']); exit; }
  if (!is_array($maps)) {
    $jsonMap = json_decode($profile['json_text'] ?? '', true);
    $maps = $engine->getMaps($jsonMap);
    foreach ($maps as &$m) {
      $origStart = $engine->parseAddr($m['Fieldvalues.StartAddr'] ?? $m['StartAddr'] ?? $m['start'] ?? '$0');
      $m['detected_addr'] = $origStart;
    }
  }

  $patchTables = $profile['patch_tables'] ?? [];
  if (is_string($patchTables)) { $tmp = json_decode($patchTables, true); if (is_array($tmp)) $patchTables = $tmp; }

  $res = $engine->applyPatch($binData, $maps, $patchTables, $selectedRows);

  $fname = "mod_" . time() . "_" . substr($token,0,6) . ".bin";
  file_put_contents($tempDir . "/$fname", $res['data']);

  echo json_encode(['status'=>'ok','url'=>"dtc_module/temp/$fname",'count'=>($res['count'] ?? 0)], JSON_UNESCAPED_UNICODE);
  exit;
}

echo json_encode(["status"=>"error","msg"=>"unknown_action"]);
