<?php
header('Content-Type: application/json');

define('TONSUI_LOADED', true);
require_once __DIR__ . '/session_init.php';
requireLogin(true);
require_once __DIR__ . '/db.php';

// Simple logger to project logs dir
function tlog($message, $context = []) {
  try {
    $root = realpath(__DIR__ . '/..');
    $logDir = $root . '/logs';
    if (!is_dir($logDir)) { @mkdir($logDir, 0755, true); }
    $line = '['.date('Y-m-d H:i:s')."] transfer_to_account - " . $message;
    if (!empty($context)) { $line .= ' | ' . json_encode($context, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE); }
    $line .= "\n";
    @error_log($line, 3, $logDir . '/transfer_errors.log');
  } catch (Throwable $e) { /* ignore */ }
}

try {
  $userId = $_SESSION['user_id'] ?? 0;
  if (!$userId) { echo json_encode(['success'=>false,'error'=>'Not authenticated']); exit; }
  $input = json_decode(file_get_contents('php://input'), true) ?: [];
  $toAcc = trim((string)($input['to_account_number'] ?? ''));
  $routing = trim((string)($input['routing_number'] ?? ''));
  $amount = floatval($input['amount'] ?? 0);
  $note = trim((string)($input['note'] ?? ''));
  tlog('incoming', ['user_id'=>$userId,'to'=>$toAcc,'routing'=>$routing,'amount'=>$amount]);

  if ($toAcc === '' || $routing === '' || $amount <= 0) {
    echo json_encode(['success'=>false,'error'=>'Invalid payload']); exit;
  }

  // Enforce account restriction flags
  $hasSusp = false; $hasTxSusp = false; $hasDormant = false;
  try { $hasSusp = $pdo->query("SHOW COLUMNS FROM users LIKE 'account_suspended'")->rowCount() > 0; } catch (Throwable $e) {}
  try { $hasTxSusp = $pdo->query("SHOW COLUMNS FROM users LIKE 'transfers_suspended'")->rowCount() > 0; } catch (Throwable $e) {}
  try { $hasDormant = $pdo->query("SHOW COLUMNS FROM users LIKE 'account_dormant'")->rowCount() > 0; } catch (Throwable $e) {}
  if ($hasSusp || $hasTxSusp || $hasDormant) {
    $sel = 'id' . ($hasSusp ? ', account_suspended' : '') . ($hasTxSusp ? ', transfers_suspended' : '') . ($hasDormant ? ', account_dormant' : '');
    $fs = $pdo->prepare("SELECT $sel FROM users WHERE id=? LIMIT 1");
    $fs->execute([$userId]);
    $flags = $fs->fetch(PDO::FETCH_ASSOC) ?: [];
    if ($hasSusp && intval($flags['account_suspended'] ?? 0) === 1) { echo json_encode(['success'=>false,'error'=>'Account is suspended']); exit; }
    if (($hasTxSusp && intval($flags['transfers_suspended'] ?? 0) === 1) || ($hasDormant && intval($flags['account_dormant'] ?? 0) === 1)) {
      echo json_encode(['success'=>false,'error'=> ($hasDormant && intval($flags['account_dormant'] ?? 0) === 1) ? 'Account is dormant' : 'Transfers are suspended']); exit;
    }
  }

  // Load routing from settings
  $expectedRouting = '110000000';
  try {
    $st = $pdo->query("SHOW TABLES LIKE 'settings'");
    if ($st && $st->rowCount() > 0) {
      $s2 = $pdo->prepare("SELECT setting_value FROM settings WHERE setting_key='routing_number' LIMIT 1");
      $s2->execute();
      $row = $s2->fetch(PDO::FETCH_ASSOC);
      if ($row && trim((string)$row['setting_value']) !== '') { $expectedRouting = trim($row['setting_value']); }
    }
  } catch (Throwable $e) {}

  if ($routing !== $expectedRouting) {
    echo json_encode(['success'=>false,'error'=>'Invalid routing number']); exit;
  }

  // Validate destination
  $hasAcc = false;
  try {
    $c = $pdo->query("SHOW COLUMNS FROM users LIKE 'account_number'");
    $hasAcc = $c && $c->rowCount() > 0;
  } catch (Throwable $e) { $hasAcc = false; }
  if (!$hasAcc) { echo json_encode(['success'=>false,'error'=>'System not configured for account transfers']); exit; }

  $dest = $pdo->prepare("SELECT id, username, name, account_number FROM users WHERE account_number=? LIMIT 1");
  $dest->execute([$toAcc]);
  $d = $dest->fetch(PDO::FETCH_ASSOC);
  if (!$d) { echo json_encode(['success'=>false,'error'=>'Destination account not found']); exit; }
  $toUserId = intval($d['id']);
  $destName = trim((string)($d['name'] ?? '')) !== '' ? trim((string)$d['name']) : (string)($d['username'] ?? '');
  if ($toUserId === intval($userId)) { echo json_encode(['success'=>false,'error'=>'Cannot transfer to your own account']); exit; }
  tlog('destination_ok', ['to_user_id'=>$toUserId,'to_name'=>$destName]);

  // Determine balance column
  $balanceCol = null; $hasBalance = false; $hasWallet = false;
  try { $c = $pdo->query("SHOW COLUMNS FROM users LIKE 'balance'"); $hasBalance = $c && $c->rowCount()>0; } catch (Throwable $e) { $hasBalance=false; }
  try { $c2 = $pdo->query("SHOW COLUMNS FROM users LIKE 'wallet_balance'"); $hasWallet = $c2 && $c2->rowCount()>0; } catch (Throwable $e) { $hasWallet=false; }
  if ($hasBalance) { $balanceCol = 'balance'; }
  elseif ($hasWallet) { $balanceCol = 'wallet_balance'; }
  else { echo json_encode(['success'=>false,'error'=>'Transfers not supported: no balance column']); exit; }

  // Check source balance
  $srcRow = $pdo->prepare("SELECT {$balanceCol} AS balance, account_number AS account_number FROM users WHERE id=? LIMIT 1");
  $srcRow->execute([$userId]);
  $src = $srcRow->fetch(PDO::FETCH_ASSOC);
  $balance = floatval($src['balance'] ?? 0);
  if ($balance < $amount) { echo json_encode(['success'=>false,'error'=>'Insufficient balance']); exit; }
  tlog('balance_ok', ['balance_col'=>$balanceCol,'src_balance'=>$balance,'amount'=>$amount]);
  $srcAccountNumber = (string)($src['account_number'] ?? '');

  // Destination balance
  $dstBalRow = $pdo->prepare("SELECT {$balanceCol} AS balance FROM users WHERE id=? LIMIT 1");
  $dstBalRow->execute([$toUserId]);
  $dstBal = $dstBalRow->fetch(PDO::FETCH_ASSOC);
  $dstBalance = floatval($dstBal['balance'] ?? 0);

  // Ensure transactions table exists BEFORE starting a transaction (avoid implicit commit)
  try {
    $pdo->exec("CREATE TABLE IF NOT EXISTS transactions (
      id INT AUTO_INCREMENT PRIMARY KEY,
      user_id INT NOT NULL,
      type VARCHAR(50) NOT NULL,
      amount DECIMAL(18,8) NOT NULL DEFAULT 0,
      status VARCHAR(32) NOT NULL DEFAULT 'completed',
      details TEXT NULL,
      reference VARCHAR(64) NULL,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      INDEX (user_id), INDEX (type), INDEX (status)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
  } catch (Throwable $e) { /* ignore */ }

  // Generate a reference for this transfer
  $ref = '';
  try {
    $ref = 'TRF-' . strtoupper(dechex(time())) . '-' . substr(bin2hex(random_bytes(4)), 0, 8);
  } catch (Throwable $e) {
    $ref = 'TRF-' . strtoupper(dechex(time()));
  }

  // Do transfer atomically
  $pdo->beginTransaction(); tlog('tx_begin');
  try {
    // Debit source
    $deb = $pdo->prepare("UPDATE users SET {$balanceCol} = {$balanceCol} - ? WHERE id=?");
    $deb->execute([$amount, $userId]);

    // Credit destination
    $cre = $pdo->prepare("UPDATE users SET {$balanceCol} = {$balanceCol} + ? WHERE id=?");
    $cre->execute([$amount, $toUserId]);

    // Insert transactions
    $ins = $pdo->prepare("INSERT INTO transactions (user_id, type, amount, status, details, reference, created_at) VALUES (?,?,?,?,?,?,NOW())");
    // Use common values likely supported across variants: 'withdrawal' and 'deposit'
    $ins->execute([$userId, 'withdrawal', -abs($amount), 'completed', json_encode(['to_account'=>$toAcc,'routing'=>$routing,'note'=>$note,'kind'=>'internal_transfer']), $ref]);
    $ins->execute([$toUserId, 'deposit', abs($amount), 'completed', json_encode(['from_user'=>$userId,'routing'=>$routing,'note'=>$note,'kind'=>'internal_transfer']), $ref]);

    $pdo->commit(); tlog('tx_commit');
  } catch (Throwable $e) {
    if ($pdo->inTransaction()) { $pdo->rollBack(); }
    tlog('tx_rollback', ['err'=>$e->getMessage()]);
    throw $e;
  }

  // Determine currency for response (optional column on users)
  $currency = 'EUR';
  try {
    $hasCurr = false; $cols = $pdo->query("SHOW COLUMNS FROM users");
    while ($c = $cols->fetch(PDO::FETCH_ASSOC)) { if (strtolower($c['Field'] ?? '') === 'account_currency') { $hasCurr = true; break; } }
    if ($hasCurr) {
      $cs = $pdo->prepare('SELECT account_currency FROM users WHERE id=? LIMIT 1');
      $cs->execute([$userId]);
      $row = $cs->fetch(PDO::FETCH_ASSOC);
      $cc = strtoupper(trim((string)($row['account_currency'] ?? '')));
      if ($cc !== '') { $currency = $cc; }
    }
  } catch (Throwable $e) { /* ignore */ }

  try {
    require_once __DIR__ . '/email_helper.php';
    $srcInfo = null; $dstInfo = null;
    try {
      $s = $pdo->prepare('SELECT email, username, name FROM users WHERE id=? LIMIT 1');
      $s->execute([$userId]);
      $srcInfo = $s->fetch(PDO::FETCH_ASSOC) ?: null;
    } catch (Throwable $ie) {}
    try {
      $s = $pdo->prepare('SELECT email, username, name FROM users WHERE id=? LIMIT 1');
      $s->execute([$toUserId]);
      $dstInfo = $s->fetch(PDO::FETCH_ASSOC) ?: null;
    } catch (Throwable $ie) {}
    $now = date('Y-m-d H:i');
    $srcNewBalance = $balance - $amount;
    $dstNewBalance = $dstBalance + $amount;
    if ($srcInfo && !empty($srcInfo['email'])) {
      $resp = @sendEmail($pdo, $srcInfo['email'], 'internalTransferSent', [
        'user_name' => ($srcInfo['name'] ?: $srcInfo['username'] ?: 'User'),
        'amount' => number_format($amount, 2),
        'currency' => $currency,
        'to_account' => $toAcc,
        'reference' => $ref,
        'date' => $now,
        'account_number' => $srcAccountNumber,
        'available_balance' => number_format($srcNewBalance, 2) . ' ' . $currency,
      ]);
      if (!$resp || (isset($resp['success']) && $resp['success'] === false)) {
        try { tlog('email_send_failed', ['template'=>'internalTransferSent','resp'=>$resp]); } catch (Throwable $le) {}
        try {
          require_once __DIR__ . '/includes/Mailer.php';
          if (class_exists('Mailer')) {
            $mailer = new Mailer();
            // Try to render styled template from DB or defaults
            $subject = 'Transfer Completed - ' . ($srcInfo['name'] ?: $srcInfo['username'] ?: '');
            $html = '';
            $vars = [
              'user_name' => ($srcInfo['name'] ?: $srcInfo['username'] ?: 'User'),
              'amount' => number_format($amount, 2),
              'currency' => $currency,
              'to_account' => $toAcc,
              'reference' => $ref,
              'date' => $now,
              'account_number' => $srcAccountNumber,
              'available_balance' => number_format($srcNewBalance, 2) . ' ' . $currency,
            ];
            try {
              if (function_exists('getEmailConfig')) { $cfg = getEmailConfig($pdo); }
              $tpl = $cfg['templates']['internalTransferSent'] ?? null;
              if (!$tpl && function_exists('getDefaultTemplates')) {
                $defs = getDefaultTemplates();
                $tpl = $defs['internalTransferSent'] ?? null;
              }
              if ($tpl) {
                $subject = $tpl['subject'];
                $html = $tpl['body'];
                foreach ($vars as $k => $v) { $subject = str_replace('{{'.$k.'}}', $v, $subject); $html = str_replace('{{'.$k.'}}', $v, $html); }
                // brand placeholders via settings if available
                if (!empty($cfg['settings'])) {
                  foreach (['brand_name','brand_email','brand_logo_url','brand_address'] as $bk) {
                    if (isset($cfg['settings'][$bk])) { $html = str_replace('{{'.$bk.'}}', $cfg['settings'][$bk], $html); $subject = str_replace('{{'.$bk.'}}', $cfg['settings'][$bk], $subject); }
                  }
                  if (!empty($cfg['settings']['brand_email']) && strpos($cfg['settings']['brand_email'], '@') !== false) {
                    $domain = substr(strrchr($cfg['settings']['brand_email'], '@'), 1);
                    $html = str_replace('{{fraud_email}}', 'frauddesk@'.$domain, $html);
                    $subject = str_replace('{{fraud_email}}', 'frauddesk@'.$domain, $subject);
                  }
                }
                if (strpos($html, "\\n") !== false) { $html = str_replace(["\\r\\n","\\n"], "\n", $html); }
                if (strpos($html, "\\t") !== false) { $html = str_replace("\\t", "    ", $html); }
              }
            } catch (Throwable $re) {}
            if ($html === '') {
              // Minimal fallback if template fetch failed
              $html = '<h2>Transfer Completed</h2><p>Dear ' . htmlspecialchars($srcInfo['name'] ?: $srcInfo['username']) . ',</p><p>Your internal transfer has been completed.</p><p><strong>Amount:</strong> ' . htmlspecialchars(number_format($amount, 2)) . ' ' . htmlspecialchars($currency) . '<br/><strong>To Account:</strong> ' . htmlspecialchars($toAcc) . '</p>';
            }
            $text = strip_tags($html);
            $mailer->sendEmail($srcInfo['email'], $subject, $html, $text);
          }
        } catch (Throwable $fe) {}
      }
    }
    if ($dstInfo && !empty($dstInfo['email'])) {
      $resp2 = @sendEmail($pdo, $dstInfo['email'], 'internalTransferReceived', [
        'user_name' => ($dstInfo['name'] ?: $dstInfo['username'] ?: 'User'),
        'amount' => number_format($amount, 2),
        'currency' => $currency,
        'from_user' => ($srcInfo['username'] ?? 'User'),
        'reference' => $ref,
        'date' => $now,
        'account_number' => (string)($d['account_number'] ?? ''),
        'available_balance' => number_format($dstNewBalance, 2) . ' ' . $currency,
      ]);
      if (!$resp2 || (isset($resp2['success']) && $resp2['success'] === false)) {
        try { tlog('email_send_failed', ['template'=>'internalTransferReceived','resp'=>$resp2]); } catch (Throwable $le) {}
        try {
          require_once __DIR__ . '/includes/Mailer.php';
          if (class_exists('Mailer')) {
            $mailer = new Mailer();
            // Try to render styled template from DB or defaults
            $subject = 'Funds Received - ' . ($dstInfo['name'] ?: $dstInfo['username'] ?: '');
            $html2 = '';
            $vars2 = [
              'user_name' => ($dstInfo['name'] ?: $dstInfo['username'] ?: 'User'),
              'amount' => number_format($amount, 2),
              'currency' => $currency,
              'from_user' => ($srcInfo['username'] ?? 'User'),
              'reference' => $ref,
              'date' => $now,
              'account_number' => (string)($d['account_number'] ?? ''),
              'available_balance' => number_format($dstNewBalance, 2) . ' ' . $currency,
            ];
            try {
              if (function_exists('getEmailConfig')) { $cfg = getEmailConfig($pdo); }
              $tpl2 = $cfg['templates']['internalTransferReceived'] ?? null;
              if (!$tpl2 && function_exists('getDefaultTemplates')) {
                $defs = getDefaultTemplates();
                $tpl2 = $defs['internalTransferReceived'] ?? null;
              }
              if ($tpl2) {
                $subject = $tpl2['subject'];
                $html2 = $tpl2['body'];
                foreach ($vars2 as $k => $v) { $subject = str_replace('{{'.$k.'}}', $v, $subject); $html2 = str_replace('{{'.$k.'}}', $v, $html2); }
                if (!empty($cfg['settings'])) {
                  foreach (['brand_name','brand_email','brand_logo_url','brand_address'] as $bk) {
                    if (isset($cfg['settings'][$bk])) { $html2 = str_replace('{{'.$bk.'}}', $cfg['settings'][$bk], $html2); $subject = str_replace('{{'.$bk.'}}', $cfg['settings'][$bk], $subject); }
                  }
                  if (!empty($cfg['settings']['brand_email']) && strpos($cfg['settings']['brand_email'], '@') !== false) {
                    $domain = substr(strrchr($cfg['settings']['brand_email'], '@'), 1);
                    $html2 = str_replace('{{fraud_email}}', 'frauddesk@'.$domain, $html2);
                    $subject = str_replace('{{fraud_email}}', 'frauddesk@'.$domain, $subject);
                  }
                }
                if (strpos($html2, "\\n") !== false) { $html2 = str_replace(["\\r\\n","\\n"], "\n", $html2); }
                if (strpos($html2, "\\t") !== false) { $html2 = str_replace("\\t", "    ", $html2); }
              }
            } catch (Throwable $re) {}
            if ($html2 === '') {
              // Minimal fallback if template fetch failed
              $html2 = '<h2>Funds Received</h2><p>Dear ' . htmlspecialchars($dstInfo['name'] ?: $dstInfo['username']) . ',</p><p>You have received an internal transfer.</p><p><strong>Amount:</strong> ' . htmlspecialchars(number_format($amount, 2)) . ' ' . htmlspecialchars($currency) . '<br/><strong>From:</strong> ' . htmlspecialchars($srcInfo['username'] ?? 'User') . '</p>';
            }
            $text2 = strip_tags($html2);
            $mailer->sendEmail($dstInfo['email'], $subject, $html2, $text2);
          }
        } catch (Throwable $fe) {}
      }
    }
  } catch (Throwable $e) { /* ignore */ }

  echo json_encode([
    'success'=>true,
    'transfer'=>[
      'to_account_number' => $toAcc,
      'to_user_name' => $destName,
      'amount' => $amount,
      'currency' => $currency,
      'expected_delivery' => 'instantly'
    ]
  ]);
} catch (Throwable $e) {
  http_response_code(500);
  tlog('exception', ['message'=>$e->getMessage(),'file'=>$e->getFile(),'line'=>$e->getLine()]);
  $debug = '0';
  try {
    if (class_exists('TonEnv')) { $debug = TonEnv::get('APP_DEBUG', '0'); }
    else { $debug = $_ENV['APP_DEBUG'] ?? ($_SERVER['APP_DEBUG'] ?? '0'); }
  } catch (Throwable $ie) {}
  $payload = ['success'=>false,'error'=>'Server error'];
  if ($debug === '1' || strtolower((string)$debug) === 'true') {
    $payload['detail'] = $e->getMessage();
  }
  echo json_encode($payload);
}
