<?php
require_once __DIR__ . '/../config.php';
// require_admin();


$db = contracts_db();
mysqli_set_charset($db, 'utf8mb4');             // <-- juda muhim
$db->query("SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci");
$db->query("SET time_zone = '+05:00'");


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

if (!function_exists('json_out')) {
  function json_out($data, $code=200){
    http_response_code($code);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($data, JSON_UNESCAPED_UNICODE);
    exit;
  }
}
function json_bad($msg, $code=400){ json_out(['ok'=>false,'error'=>$msg], $code); }

$db = contracts_db();
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$action = $_GET['action'] ?? '';

/* ---------- Helpers ---------- */
function norm_str($s){ return is_string($s) ? trim($s) : ''; }
function norm_int($v){ return (int)$v; }
function bool01($v){ return !empty($v) ? 1 : 0; }
function esc_like($db,$s){ return $db->real_escape_string($s); }

function ensure_upload_dir($base){
  if (is_dir($base)) return is_writable($base);
  // rekursiv mkdir
  if (!@mkdir($base, 0755, true)) {
    error_log("contracts.php ensure_upload_dir: mkdir failed: $base");
    return false;
  }
  if (!is_writable($base)) {
    @chmod($base, 0755);
  }
  return is_writable($base);
}
function safe_filename($name){
  $name = preg_replace('/[^\w\-. ]+/u','_', (string)$name);
  $name = preg_replace('/_+/', '_', $name);
  return $name ?: ('file_'.time());
}
function detect_mime($path, $fallback='application/octet-stream'){
  if (function_exists('finfo_open')) {
    $f = finfo_open(FILEINFO_MIME_TYPE);
    if ($f) {
      $m = finfo_file($f, $path);
      finfo_close($f);
      if ($m) return $m;
    }
  }
  return $fallback;
}

/* ========== CREATE (multipart) ========== */
if ($method==='POST' && $action==='create') {
  $payload = $_POST['payload'] ?? '';
  if(!$payload){ json_bad('payload topilmadi'); }
  $in = json_decode($payload, true);
  if(!is_array($in)){ json_bad('payload JSON xato'); }

  $title   = norm_str($in['title'] ?? '');
  $ym      = norm_str($in['ym'] ?? '');
  $plan_id = norm_int($in['plan_id'] ?? 0);
  $req_sig = bool01($in['require_signature'] ?? 1);
  $note    = norm_str($in['admin_note'] ?? '');
  $items   = $in['items'] ?? [];
  $op_ids  = $in['operator_ids'] ?? [];

  if(!$title || !$ym || !$plan_id) json_bad('title, ym, plan_id shart');
  if(!is_array($items) || count($items)==0) json_bad('Kamida bitta punkt kerak');
  if(!is_array($op_ids) || count($op_ids)==0) json_bad('Kamida bitta operator kerak');

  $uid = (int)(current_user()['id'] ?? 0);

  $db->begin_transaction();
  try {
    $st=$db->prepare("INSERT INTO contract_groups (title,ym,plan_id,require_signature,admin_note,created_by) VALUES (?,?,?,?,?,?)");
    if(!$st) throw new Exception('prepare cg: '.$db->error);
    $st->bind_param("ssiisi", $title, $ym, $plan_id, $req_sig, $note, $uid);
    if(!$st->execute()) throw new Exception('exec cg: '.$st->error);
    $group_id = $st->insert_id;

    $sti=$db->prepare("INSERT INTO contract_group_items (group_id,item_id,evidence_types) VALUES (?,?,?)");
    if(!$sti) throw new Exception('prepare cgi: '.$db->error);
    foreach($items as $it){
      $item_id = norm_int($it['item_id'] ?? 0);
      $ev      = norm_str($it['evidence_types'] ?? '');
      if($item_id<=0) continue;
      $sti->bind_param("iis", $group_id, $item_id, $ev);
      if(!$sti->execute()) throw new Exception('exec cgi: '.$sti->error);
    }

    $stc=$db->prepare("INSERT INTO contracts (group_id,operator_id,status) VALUES (?,?, 'pending')");
    if(!$stc) throw new Exception('prepare contracts: '.$db->error);
    foreach($op_ids as $oid){
      $op = norm_int($oid);
      if($op<=0) continue;
      $stc->bind_param("ii", $group_id, $op);
      if(!$stc->execute()) throw new Exception('exec contracts: '.$stc->error);
    }

    // attachments
    $hasFiles = isset($_FILES['files']) && is_array($_FILES['files']['name']);
    if($hasFiles){
      $ymDir = preg_replace('/[^0-9]/','', substr($ym,0,7)); // 'YYYYMM'
      $base = realpath(__DIR__ . '/..') . '/uploads/contracts/' . $ymDir . '/' . $group_id;
      if(!ensure_upload_dir($base)) throw new Exception('Upload katalogi yaratilmadi: '.$base);

      $sta=$db->prepare("INSERT INTO contract_attachments (group_id,file_name,file_path,mime,size_bytes) VALUES (?,?,?,?,?)");
      if(!$sta) throw new Exception('prepare attach: '.$db->error);

      $names = $_FILES['files']['name'];
      $tmps  = $_FILES['files']['tmp_name'];
      $types = $_FILES['files']['type'];
      $sizes = $_FILES['files']['size'];
      $errs  = $_FILES['files']['error'];
      $n = count($names);

      for($i=0;$i<$n;$i++){
        if($errs[$i]!==UPLOAD_ERR_OK || !$tmps[$i]) {
          error_log("contracts.php create: skip file idx $i, err=".$errs[$i]);
          continue;
        }
        $origName = safe_filename($names[$i]);
        $destName = time().'_'.bin2hex(random_bytes(4)).'_'.$origName;
        $destPath = $base . '/' . $destName;

        if(!move_uploaded_file($tmps[$i], $destPath)){
          error_log("contracts.php create: move_failed; try copy tmp=".$tmps[$i]." dest=".$destPath);
          if(!@copy($tmps[$i], $destPath)) throw new Exception('Fayl saqlanmadi: '.$origName);
          @unlink($tmps[$i]);
        }

        $mime = $types[$i] ?: detect_mime($destPath,'application/octet-stream');
        $size = (int)($sizes[$i] ?? @filesize($destPath));

        $relBase = '/uploads/contracts/' . $ymDir . '/' . $group_id . '/';
        $relPath = $relBase . $destName;

        $sta->bind_param("isssi", $group_id, $origName, $relPath, $mime, $size);
        if(!$sta->execute()) throw new Exception('exec attach: '.$sta->error);
      }
    }

    $db->commit();
    json_out(['ok'=>true, 'group_id'=>$group_id]);
  } catch (Exception $ex){
    $db->rollback();
    error_log("contracts.php create error: ".$ex->getMessage());
    json_bad($ex->getMessage(), 500);
  }
}

/* ========== LIST ========== */
/* ========== LIST ========== */
if ($method==='GET' && $action==='list') {
  $status = $_GET['status'] ?? 'pending';
  if(!in_array($status,['pending','signed'])) json_bad('status noto‘g‘ri');

  $q     = trim($_GET['q'] ?? '');
  $page  = max(1, (int)($_GET['page'] ?? 1));
  $limit = max(1, min(100, (int)($_GET['limit'] ?? 10)));
  $off   = ($page-1)*$limit;

  $where = "WHERE c.status='$status'";

  $mine = isset($_GET['mine']) ? (int)$_GET['mine'] : 0;
  if ($mine===1) {
    $me = (int) (current_user()['operator_id'] ?? 0);
    $where .= " AND c.operator_id = $me";
  } elseif (!empty($_GET['operator_id'])) {
    $where .= " AND c.operator_id = ".(int)$_GET['operator_id'];
  }

  if($q!==''){
    $qq = esc_like($db,$q);
    $where .= " AND (cg.title LIKE '%$qq%' OR p.name LIKE '%$qq%' OR o.name LIKE '%$qq%' OR o.username LIKE '%$qq%')";
  }

  $sql = "SELECT SQL_CALC_FOUND_ROWS
            c.id,
            c.created_at,
            cg.title AS contract_title,
            cg.ym,
            p.name AS plan_name,
            o.name AS operator_name
          FROM contracts c
          JOIN contract_groups cg ON cg.id=c.group_id
          JOIN kpi_plans p ON p.id=cg.plan_id
          LEFT JOIN operators o ON o.id=c.operator_id
          $where
          ORDER BY c.created_at DESC
          LIMIT $off,$limit";

  $rows = [];
  $r = $db->query($sql);
  if(!$r){ json_bad('DB error: '.$db->error, 500); }
  while($x=$r->fetch_assoc()) $rows[]=$x;

  $fr = $db->query("SELECT FOUND_ROWS() x");
  $total = (int)($fr ? ($fr->fetch_assoc()['x'] ?? 0) : 0);

  json_out(['ok'=>true,'rows'=>$rows,'total'=>$total,'page'=>$page,'limit'=>$limit]);
}


/* ========== DETAIL ========== */
if ($method==='GET' && $action==='detail') {
  $id = (int)($_GET['id'] ?? 0);
  if($id<=0) json_bad('id shart');

  $sql = "SELECT c.id, c.status, c.created_at, c.signed_at,
                 cg.title, cg.ym, cg.plan_id, cg.require_signature, cg.admin_note,
                 p.name AS plan_name,
                 o.name AS operator_name
          FROM contracts c
          JOIN contract_groups cg ON cg.id=c.group_id
          LEFT JOIN kpi_plans p ON p.id=cg.plan_id
          LEFT JOIN operators o ON o.id=c.operator_id
          WHERE c.id=$id";
  $r = $db->query($sql);
  if(!$r || !$r->num_rows){ json_bad('Topilmadi', 404); }
  $row = $r->fetch_assoc();

  $items = [];
  $ri = $db->query("SELECT cgi.item_id, ki.title, cgi.evidence_types
                    FROM contract_group_items cgi
                    LEFT JOIN kpi_items ki ON ki.id=cgi.item_id
                    WHERE cgi.group_id = (SELECT group_id FROM contracts WHERE id=$id)");
  if($ri){ while($x=$ri->fetch_assoc()) $items[]=$x; }

  $atts = [];
  $ra = $db->query("SELECT file_name AS name, file_path AS url, mime FROM contract_attachments
                    WHERE group_id = (SELECT group_id FROM contracts WHERE id=$id)
                    ORDER BY id DESC");
  if($ra){ while($x=$ra->fetch_assoc()) $atts[]=$x; }

  // oxirgi imzo
  $sig = null;
  $rs = $db->query("SELECT typed_name, image_path, image_mime, created_at
                    FROM contract_signatures WHERE contract_id=$id
                    ORDER BY id DESC LIMIT 1");
  if($rs && $rs->num_rows){ $sig = $rs->fetch_assoc(); }

  $out = [
    'ok'=>true,
    'id'=>$row['id'],
    'status'=>$row['status'],
    'created_at'=>$row['created_at'],
    'signed_at'=>$row['signed_at'],
    'title'=>$row['title'],
    'ym'=>$row['ym'],
    'plan_id'=>$row['plan_id'],
    'plan_name'=>$row['plan_name'],
    'operator_name'=>$row['operator_name'],
    'require_signature'=> (int)$row['require_signature'],
    'admin_note'=>$row['admin_note'],
    'items'=>$items,
    'attachments'=>$atts,
    'signature'=>$sig
  ];
  json_out($out);
}

/* ========== SIGN ========== */
if ($method==='POST' && $action==='sign') {
  $id = 0; $typed = ''; $agree = 0; $png_tmp = null; $png_name = null; $png_mime = null; $from_json_tmp = false;

  if (isset($_POST['id']) || isset($_FILES['signature_png'])) {
    $id    = (int)($_POST['id'] ?? 0);
    $typed = norm_str($_POST['typed_name'] ?? '');
    $agree = !empty($_POST['agree']) ? 1 : 0;
    if (isset($_FILES['signature_png']) && is_uploaded_file($_FILES['signature_png']['tmp_name'])) {
      $png_tmp  = $_FILES['signature_png']['tmp_name'];
      $png_name = $_FILES['signature_png']['name'];
      $png_mime = $_FILES['signature_png']['type'] ?: 'image/png';
    }
  } else {
    $in = json_decode(file_get_contents('php://input'), true);
    if (!is_array($in)) json_bad('Bad JSON');
    $id    = (int)($in['id'] ?? 0);
    $typed = norm_str($in['typed_name'] ?? '');
    $agree = !empty($in['agree']) ? 1 : 0;
    if (!empty($in['draw_data']) && is_string($in['draw_data'])) {
      if (preg_match('/^data:(image\/[a-zA-Z0-9.+-]+);base64,(.*)$/', $in['draw_data'], $m)) {
        $png_mime = $m[1]; $data = base64_decode($m[2]);
        $tmp = tempnam(sys_get_temp_dir(), 'sig_');
        if ($tmp === false || file_put_contents($tmp, $data) === false) {
          error_log('contracts.php sign: cannot write temp from draw_data');
        } else {
          $png_tmp = $tmp; $png_name = 'signature.png'; $from_json_tmp = true;
        }
      }
    }
  }

  if ($id<=0) json_bad('id shart');
  if (!$agree) json_bad('Rozilik (agree) shart');

  $me = (int)(current_user()['operator_id'] ?? 0);
  if ($me<=0) json_bad('Auth kerak', 401);

  $sql = "SELECT c.id, c.operator_id, c.status, cg.require_signature, cg.ym
          FROM contracts c
          JOIN contract_groups cg ON cg.id=c.group_id
          WHERE c.id=$id";
  $r = $db->query($sql);
  if(!$r || !$r->num_rows) json_bad('Topilmadi', 404);
  $row = $r->fetch_assoc();

  if ((int)$row['operator_id'] !== (int)$me) json_bad('Ruxsat yo‘q', 403);
  if ($row['status'] === 'signed') json_bad('Allaqachon imzolangan', 409);

  $need_sig = (int)$row['require_signature'] === 1;
  if ($need_sig && ($typed==='' && !$png_tmp)) {
    json_bad('Imzo majburiy: typed name yoki chizilgan imzo kerak');
  }

  $db->begin_transaction();
  try {
    $st = $db->prepare("UPDATE contracts SET status='signed', signed_at=NOW(), signed_by=? WHERE id=?");
    if(!$st) throw new Exception($db->error);
    $st->bind_param("ii", $me, $id);
    if(!$st->execute()) throw new Exception($st->error);

    $img_rel = null; $img_mime = null;
    if ($png_tmp) {
      $ymDir = preg_replace('/[^0-9]/','', substr($row['ym'] ?? date('Y-m'),0,7));
      $base = realpath(__DIR__ . '/..') . '/uploads/contracts_sign/' . $ymDir . '/' . $id;
      if(!ensure_upload_dir($base)) throw new Exception('Upload dir yozilmaydi: '.$base);

      $safe = safe_filename($png_name ?: 'signature.png');
      $dest = $base.'/'.time().'_'.bin2hex(random_bytes(3)).'_'.$safe;

      // FormData tmp -> move; JSON tmp -> rename/copy
      if (!$from_json_tmp) {
        if (!@move_uploaded_file($png_tmp, $dest)) {
          error_log("contracts.php sign: move_uploaded_file failed; try copy tmp=".$png_tmp);
          if(!@copy($png_tmp, $dest)) throw new Exception('Imzo fayl saqlanmadi (copy)');
          @unlink($png_tmp);
        }
      } else {
        if (!@rename($png_tmp, $dest)) {
          if(!@copy($png_tmp, $dest)) throw new Exception('Imzo fayl saqlanmadi (rename/copy)');
          @unlink($png_tmp);
        }
      }

      $img_mime = $png_mime ?: detect_mime($dest, 'image/png');
      $relBase  = '/oylik2/uploads/contracts_sign/' . $ymDir . '/' . $id . '/';
      $img_rel  = $relBase . basename($dest);
    }

    $st2 = $db->prepare("INSERT INTO contract_signatures (contract_id, signer_id, typed_name, image_path, image_mime) VALUES (?,?,?,?,?)");
    if(!$st2) throw new Exception($db->error);
    $st2->bind_param("iisss", $id, $me, $typed, $img_rel, $img_mime);
    if(!$st2->execute()) throw new Exception($st2->error);

    $db->commit();
    json_out(['ok'=>true]);
  } catch (Exception $ex){
    $db->rollback();
    error_log("contracts.php sign error: ".$ex->getMessage());
    json_bad($ex->getMessage(), 500);
  }
}

json_bad('Unknown action', 404);
