<?php require_once __DIR__ . '/../config.php'; require_operator(); ?>
<!doctype html>
<html lang="uz">
<head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hodim portali</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
<style>
.progress-sm { height:8px }
.badge-soft { background:#f1f5ff; color:#0d6efd }
.canvas-wrap { border:1px dashed #bbb; border-radius:8px; background:#fff; }
.table-sticky thead th { position: sticky; top: 0; background:#fff; z-index:2; }
.badge-stats { font-size:.8rem; background:#f8f9fa; color:#333; border:1px solid #e9ecef; }

/* Imzo canvasi: mobil/planwet uchun to‘liq tayyor */
#signPad{
  touch-action:none;
  -ms-touch-action:none;
  user-select:none;
  -webkit-user-select:none;
  -webkit-touch-callout:none;
}
.canvas-wrap{ overscroll-behavior:contain; }
</style>
</head>
<body class="bg-light">
<nav class="navbar navbar-expand-lg navbar-dark" style="background:#1e90ff;">
  <div class="container">
    <a class="navbar-brand fw-bold" href="#">Hodim portali</a>
    <ul class="navbar-nav ms-auto">
      <li class="nav-item"><a class="nav-link active" href="./op_dashboard.php">Dashboard</a></li>
      <li class="nav-item"><a class="nav-link" href="./op_plans.php">Mening rejalarim</a></li>
      <li class="nav-item"><a class="nav-link" href="./operator_sign.php">Mening shartnomalarim</a></li>
      <li class="nav-item"><a class="nav-link" href="./logout.php">Chiqish</a></li>
    </ul>
  </div>
</nav>

<div class="container my-3">
  <div id="alertBox"></div>

  <div class="row g-2 align-items-end mb-3">
    <div class="col-sm-3"><label class="form-label">Oy</label><input type="month" id="ym" class="form-control" value="<?php echo date('Y-m'); ?>"></div>
    <div class="col-sm-9 text-end"><button class="btn btn-primary" id="btnReload">Yangilash</button> <a class="btn btn-outline-secondary ms-2" href="./op_attendance.php">Keldi / Ketdi</a></div>
  </div>

  <ul class="nav nav-tabs" id="tabNav" role="tablist">
    <li class="nav-item" role="presentation"><button class="nav-link active" id="t1-tab" data-bs-toggle="tab" data-bs-target="#t1" type="button" role="tab">1) Dalil yuborish</button></li>
    <li class="nav-item" role="presentation"><button class="nav-link" id="t2-tab" data-bs-toggle="tab" data-bs-target="#t2" type="button" role="tab">2) So‘nggi dalillar</button></li>
    <li class="nav-item" role="presentation"><button class="nav-link" id="t3-tab" data-bs-toggle="tab" data-bs-target="#t3" type="button" role="tab">3) Grafikalar</button></li>
    <li class="nav-item" role="presentation"><button class="nav-link" id="t4-tab" data-bs-toggle="tab" data-bs-target="#t4" type="button" role="tab">4) Oylik tasdiqlash</button></li>
  </ul>

  <div class="tab-content border-start border-end border-bottom p-3 bg-white">
    <!-- 1) Yuborish -->
    <div class="tab-pane fade show active" id="t1" role="tabpanel">
      <div id="plansUpload"></div>
    </div>

    <!-- 2) So‘nggi dalillar -->
    <div class="tab-pane fade" id="t2" role="tabpanel">
      <div class="table-responsive">
        <table class="table table-sm align-middle table-sticky" id="tblSubs">
          <thead class="table-light"><tr><th>Vaqt</th><th>Plan/Punkt</th><th>Dalil</th><th>Status</th><th>Amal</th></tr></thead>
          <tbody></tbody>
        </table>
      </div>
      <div class="d-flex justify-content-between align-items-center mt-2">
        <div class="text-muted small" id="subsRange">0–0</div>
        <ul class="pagination pagination-sm mb-0" id="subsPager"></ul>
      </div>
    </div>

    <!-- 3) Grafikalar -->
    <div class="tab-pane fade" id="t3" role="tabpanel">
      <div class="row g-3">
        <div class="col-md-4"><div class="card"><div class="card-body"><canvas id="chPie"></canvas></div></div></div>
        <div class="col-md-8"><div class="card"><div class="card-body"><canvas id="chBar"></canvas></div></div></div>
        <div class="col-12"><div class="card"><div class="card-body"><canvas id="chLine"></canvas></div></div></div>
      </div>
    </div>

    <!-- 4) Oylik tasdiqlash -->
    <div class="tab-pane fade" id="t4" role="tabpanel">
      <div id="salaryBox" class="mb-3"></div>
      <div id="signBox" class="d-none">
        <div class="mb-2"><strong>Imzo:</strong></div>
        <div class="canvas-wrap p-2">
          <canvas id="signPad"></canvas>
        </div>
        <div class="mt-2 d-flex gap-2">
          <button class="btn btn-outline-secondary" id="btnClearSign">Tozalash</button>
          <button class="btn btn-success" id="btnSaveSign">Imzoni saqlash</button>
        </div>
        <div class="text-muted small mt-2">Eslatma: barmoq/stilus bilan chizing. Noqulay bo‘lsa “Tozalash” bilan qayta chizing.</div>
      </div>
      <div id="signedInfo" class="d-none"></div>
    </div>
  </div>
</div>

<!-- VIEW modal -->
<div class="modal fade" id="viewModal" tabindex="-1">
  <div class="modal-dialog modal-lg modal-dialog-scrollable"><div class="modal-content">
    <div class="modal-header"><h5 class="modal-title">Dalil</h5><button class="btn-close" data-bs-dismiss="modal"></button></div>
    <div class="modal-body" id="vBody"></div>
  </div></div>
</div>

<!-- EDIT modal -->
<div class="modal fade" id="editModal" tabindex="-1">
  <div class="modal-dialog"><div class="modal-content">
    <div class="modal-header bg-info text-white"><h5 class="modal-title">Dalil (tahrirlash)</h5><button class="btn-close btn-close-white" data-bs-dismiss="modal"></button></div>
    <div class="modal-body">
      <input type="hidden" id="eId">
      <input type="hidden" id="eItemId">
      <input type="hidden" id="eUserPrev">
      <div class="mb-2">
        <label class="form-label">Matn</label>
        <textarea id="eText" class="form-control" rows="3" placeholder="Matn (ixtiyoriy)"></textarea>
      </div>
      <div class="mb-2">
        <label class="form-label">Faylni almashtirish</label>
        <input id="eFile" type="file" class="form-control">
        <div class="form-text">Agar tanlasangiz, eski fayl o‘rniga yoziladi. (Dublikat tekshiriladi)</div>
      </div>
      <div class="small text-muted" id="eInfo"></div>
    </div>
    <div class="modal-footer">
      <button class="btn btn-secondary" data-bs-dismiss="modal">Bekor</button>
      <button class="btn btn-primary" id="eSave">Saqlash</button>
    </div>
  </div></div>
</div>

<!-- NOTICE MODAL -->
<div class="modal fade" id="noticeModal" tabindex="-1">
  <div class="modal-dialog"><div class="modal-content">
    <div class="modal-header"><h5 class="modal-title">Ogohlantirish</h5><button class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div>
    <div class="modal-body" id="noticeBody">...</div>
    <div class="modal-footer"><button class="btn btn-secondary" data-bs-dismiss="modal">Yopish</button></div>
  </div></div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
/* ================= helpers ================= */
const elYM = document.getElementById('ym');
document.getElementById('btnReload').addEventListener('click', reloadAll);
function esc(s){ return (s||'').replace(/[&<>"']/g, m=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;', "'":'&#39;'}[m])); }
function showAlert(msg,type){ const box=document.getElementById('alertBox'); box.innerHTML=`<div class="alert alert-${type||'danger'}">${esc(msg)}</div>`; setTimeout(()=>box.innerHTML='',5000); }
function showNotice(html){ const b=document.getElementById('noticeBody'); b.innerHTML=html; bootstrap.Modal.getOrCreateInstance(document.getElementById('noticeModal')).show(); }
function fmtUZS(n){ return new Intl.NumberFormat('uz-UZ').format(Math.round(n||0))+" so'm"; }
function toPct(x){ return (Math.round((x||0)*1000)/10).toFixed(1)+'%'; }
async function sha256OfFile(file){ const buf=await file.arrayBuffer(); const h=await crypto.subtle.digest('SHA-256',buf); return Array.from(new Uint8Array(h)).map(b=>b.toString(16).padStart(2,'0')).join(''); }
async function sha256OfText(txt){ const enc=new TextEncoder().encode(txt); const h=await crypto.subtle.digest('SHA-256',enc); return Array.from(new Uint8Array(h)).map(b=>b.toString(16).padStart(2,'0')).join(''); }

async function reloadAll(){ await loadUploadUI(); await loadSubs(); await loadCharts(); await loadSalary(); }

/* ================= 1) Upload UI ================= */
async function loadUploadUI(){
  const ym = elYM.value;
  try{
    // Approved agregatsiya
    const subRes = await fetch('../api/submissions.php?action=list&ym='+encodeURIComponent(ym));
    const subJson = await subRes.json();
    const approvedById = new Map(), approvedByTitle = new Map();
    (subJson.rows||[]).forEach(r=>{
      if(r.status!=='approved') return;
      if(typeof r.item_id!=='undefined' && r.item_id!==null){
        approvedById.set(String(r.item_id), (approvedById.get(String(r.item_id))||0)+1);
      }else if(r.item_title){
        const t = String(r.item_title).toLowerCase();
        approvedByTitle.set(t, (approvedByTitle.get(t)||0)+1);
      }
    });

    // Planlar
    const r=await fetch('../api/op_my_plans.php?ym='+encodeURIComponent(ym));
    const d=await r.json();
    const box=document.getElementById('plansUpload'); box.innerHTML='';

    (d.plans||[]).forEach((p,pi)=>{
      const accId   = 'acc_'+pi;
      const planId  = (p?.plan?.id ?? p?.plan_id ?? 0);
      const planName= (p?.plan?.name ?? p?.plan_name ?? 'Plan');
      let itemsHtml = '';

      (p.items||[]).forEach((it,i)=>{
        const ev = String(it.evidence_types||'').split(/[,\s]+/).map(s=>s.trim().toLowerCase()).filter(Boolean);
        const target = Number(it.target_int||0);
        const done   = (approvedById.get(String(it.id)) ?? approvedByTitle.get(String(it.title||'').toLowerCase()) ?? 0);
        const left   = Math.max(0, target - done);

        const ACCEPT_MAP = {
          image : 'image/*', audio : 'audio/*', video : 'video/*',
          file  : [
            '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.zip,.rar,.7z,.txt,.csv',
            'text/plain','text/csv','application/pdf',
            'application/msword','application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/vnd.ms-excel','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'application/vnd.ms-powerpoint','application/vnd.openxmlformats-officedocument.presentationml.presentation',
            'application/zip','application/x-rar-compressed','application/x-7z-compressed'
          ].join(',')
        };
        const needText = ev.includes('text');
        const needUser = ev.includes('username');
        const fileKinds= ['image','audio','video','file'].filter(k=> ev.includes(k));
        const accept   = fileKinds.map(k=>ACCEPT_MAP[k]).filter(Boolean).join(',');

        let inputs='';
        if(needText){
          inputs+=`<div class="mb-2"><label class="form-label">Matn <span class="text-danger">*</span></label>
            <textarea class="form-control" name="text_content" required></textarea></div>`;
        }
        if(needUser){
          inputs+=`<div class="mb-2"><label class="form-label">Username <span class="text-danger">*</span></label>
            <input class="form-control" name="username_ref" required></div>`;
        }
        if(fileKinds.length){
          inputs+=`<div class="mb-2"><label class="form-label">Fayl (${esc(fileKinds.join(', '))}) <span class="text-danger">*</span></label>
            <input type="file" class="form-control" name="file" accept="${accept}" required>
            <div class="form-text">Qabul qilinadigan turlar: ${esc(fileKinds.join(', '))}</div></div>`;
        }

        const collapseId = accId+'_itm_'+i;
        itemsHtml += `
        <div class="accordion-item">
          <h2 class="accordion-header">
            <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#${collapseId}">
              <div class="d-flex flex-column w-100">
                <div><strong>${esc(it.title||'')}</strong></div>
                <div class="mt-1">
                  <span class="badge badge-stats">plan: ${target}</span>
                  <span class="badge badge-stats ms-1">yuborilgan: ${done}</span>
                  <span class="badge badge-stats ms-1">qoldi: ${left}</span>
                </div>
              </div>
            </button>
          </h2>
          <div id="${collapseId}" class="accordion-collapse collapse">
            <div class="accordion-body">
              <form class="uploadForm" data-item="${it.id}" data-plan="${planId}" accept-charset="UTF-8">
                ${inputs || '<div class="text-muted">Bu punkt uchun dalil talab qilinmaydi</div>'}
                <div class="d-flex gap-2">
                  <button type="button" class="btn btn-success btn-sm doUpload">Yuborish</button>
                  <span class="dup text-danger fw-semibold d-none">⚠ Dublikat aniqlandi</span>
                  <span class="ok text-success fw-semibold d-none">✔ Saqlandi</span>
                </div>
              </form>
            </div>
          </div>
        </div>`;
      });

      const card = document.createElement('div');
      card.className='card mb-3';
      card.innerHTML = `
        <div class="card-header bg-light"><span class="badge badge-soft">${d.ym}</span> <strong>${esc(planName)}</strong></div>
        <div class="card-body"><div class="accordion" id="${accId}">${itemsHtml || '<div class="text-muted">Punkt yo‘q</div>'}</div></div>`;
      box.appendChild(card);
    });

    // Upload handler
    document.querySelectorAll('form.uploadForm .doUpload').forEach(btn=>{
      if (btn.dataset.bound) return; btn.dataset.bound = "1";
      btn.addEventListener('click', async ()=>{
        const form=btn.closest('form.uploadForm');
        const item_id=parseInt(form.dataset.item,10);
        const plan_id=parseInt(form.dataset.plan,10);
        const ym=elYM.value;

        const textEl=form.querySelector('[name=text_content]');
        const userEl=form.querySelector('[name=username_ref]');
        const fileEl=form.querySelector('[name=file]');

        const needText=!!textEl, needUser=!!userEl, needFile=!!fileEl;
        const miss=[];
        if(needText && (!textEl.value || !textEl.value.trim())) miss.push('Matn');
        if(needUser && (!userEl.value || !userEl.value.trim())) miss.push('Username');
        if(needFile && (!fileEl.files || !fileEl.files[0]))     miss.push('Fayl');

        if(needFile && fileEl.files[0]){
          const f=fileEl.files[0];
          const acc=(fileEl.getAttribute('accept')||'').split(',').map(s=>s.trim()).filter(Boolean);
          if(acc.length){
            const ok=acc.some(a=>{
              if(a.endsWith('/*')) return f.type && f.type.startsWith(a.slice(0,-1));
              if(a.startsWith('.')) return f.name && f.name.toLowerCase().endsWith(a.toLowerCase());
              return f.type===a;
            });
            if(!ok) miss.push('Fayl turi mos emas');
          }
        }
        if(miss.length){ showNotice(`<div>${esc(miss.join(', '))} talab qilinadi.</div>`); return; }

        // dublikat
        let fileHash=null, textHash=null;
        if(needFile && fileEl.files[0]) fileHash=await sha256OfFile(fileEl.files[0]);
        if(needText && textEl.value.trim()) textHash=await sha256OfText(textEl.value.trim());
        try{
          const chkRes=await fetch('../api/submissions.php?action=check',{
            method:'POST', headers:{'Content-Type':'application/json; charset=utf-8'},
            body:JSON.stringify({ym,plan_id,item_id,file_hash:fileHash||'',text_hash:textHash||''})
          });
          const chk=await chkRes.json();
          if(!chkRes.ok) throw new Error(chk.error||chkRes.statusText);
          if(chk.exists && (chk.status==='approved'||chk.status==='pending')){
            form.querySelector('.dup')?.classList.remove('d-none');
            showNotice(`<div>Bu dalil dublikati avval yuborilgan (<b>${esc(chk.status)}</b>).</div>`); return;
          }
        }catch(e){ showNotice(`<div>Dublikat tekshiruvida xato: ${esc(e.message)}</div>`); return; }

        // upload
        const fd=new FormData();
        fd.append('ym',ym); fd.append('plan_id',String(plan_id)); fd.append('item_id',String(item_id)); fd.append('tz','Asia/Tashkent');
        if(needText) fd.append('text_content',textEl.value);
        if(needUser) fd.append('username_ref',userEl.value);
        if(needFile) fd.append('file',fileEl.files[0],fileEl.files[0].name);
        if(fileHash) fd.append('file_hash',fileHash); if(textHash) fd.append('text_hash',textHash);

        try{
          const r2=await fetch('../api/submissions.php?action=upload',{method:'POST',body:fd});
          const t2=await r2.text(); if(!r2.ok) throw new Error(`HTTP ${r2.status} ${r2.statusText} — ${t2.slice(0,200)}`);
          const d2=JSON.parse(t2);
          if(d2.ok){ form.querySelector('.ok')?.classList.remove('d-none'); await reloadAll(); }
          else showNotice(`<div>Upload xatosi: ${esc(d2.error||'')}</div>`);
        }catch(e){ showNotice(`<div>Upload xatosi: ${esc(e.message)}</div>`); }
      });
    });

  }catch(e){ showAlert('Plans yuklash xatosi: '+e.message,'danger'); }
}

/* ================= 2) So‘nggi dalillar (paginatsiya + edit) ================= */
const subsState = { rows:[], page:1, limit:10 };

function renderSubs(){
  const {rows, page, limit} = subsState;
  const startIdx = (page-1)*limit;
  const slice = rows.slice(startIdx, startIdx+limit);

  const tb=document.querySelector('#tblSubs tbody'); tb.innerHTML='';
  slice.forEach(x=>{
    const when = x.created_at ? x.created_at.replace('T',' ').slice(0,19) : '';
    const dalil = x.file_path ? `<span class="badge text-bg-light">${(x.file_mime||'').split('/')[0]||'file'}</span>`
                              : (x.text_content? `<span class="badge text-bg-light">text</span>` : '-');
    const canEdit = x.status==='pending';
    const tr=document.createElement('tr'); tr.innerHTML=`
      <td>${when}</td>
      <td>${esc(x.plan_name||'')} / <strong>${esc(x.item_title||'')}</strong></td>
      <td>${dalil}</td>
      <td><span class="badge ${x.status==='approved'?'text-bg-success':(x.status==='rejected'?'text-bg-danger':'text-bg-warning text-dark')}">${x.status}</span></td>
      <td>
        <button class="btn btn-sm btn-outline-primary me-1 vBtn">Ko‘rish</button>
        ${canEdit?'<button class="btn btn-sm btn-outline-info eBtn">Tahrirlash</button>':''}
      </td>`;
    tr.dataset.json = JSON.stringify(x);
    tb.appendChild(tr);
  });

  const total = rows.length;
  const from = total ? (startIdx+1) : 0;
  const to   = Math.min(total, startIdx+limit);
  document.getElementById('subsRange').textContent = `${from}–${to}`;

  const pages = Math.max(1, Math.ceil(total/limit));
  const pg   = document.getElementById('subsPager'); pg.innerHTML='';
  const makeLi = (disabled, label, dataNav)=> {
    const li = document.createElement('li');
    li.className = 'page-item'+(disabled?' disabled':'');
    li.innerHTML = `<a class="page-link" href="#" data-nav="${dataNav||''}">${label}</a>`;
    return li;
  };
  pg.appendChild(makeLi(page<=1, 'Orqaga', 'prev'));
  pg.appendChild(makeLi(true, `${from}–${to}`, ''));
  pg.appendChild(makeLi(page>=pages, 'Keyingi', 'next'));
  pg.querySelectorAll('a.page-link').forEach(a=>{
    a.addEventListener('click', e=>{
      e.preventDefault();
      const nav = a.dataset.nav;
      if(nav==='prev' && subsState.page>1){ subsState.page--; renderSubs(); }
      if(nav==='next' && subsState.page<pages){ subsState.page++; renderSubs(); }
    });
  });

  // view modal
  document.querySelectorAll('#tblSubs .vBtn').forEach(b=>{
    if (b.dataset.bound) return; b.dataset.bound="1";
    b.addEventListener('click', ()=>{
      const x=JSON.parse(b.closest('tr').dataset.json);
      let html='';
      if(x.file_path && x.file_mime){
        if(x.file_mime.startsWith('image/')) html += `<img src="${x.file_path}" class="img-fluid rounded">`;
        else if(x.file_mime.startsWith('audio/')) html += `<audio controls class="w-100" src="${x.file_path}"></audio>`;
        else if(x.file_mime.startsWith('video/')) html += `<video controls class="w-100" src="${x.file_path}"></video>`;
        else html += `<a href="${x.file_path}" target="_blank" class="btn btn-outline-secondary">Fayl</a>`;
      }
      if(x.text_content) html += `<div class="mt-2"><strong>Matn:</strong><div class="border rounded p-2 bg-light">${esc(x.text_content)}</div></div>`;
      if(!html) html='<div class="text-muted">Fayl/matn yo‘q</div>';
      document.getElementById('vBody').innerHTML=html;
      bootstrap.Modal.getOrCreateInstance(document.getElementById('viewModal')).show();
    });
  });

  // edit modal
  document.querySelectorAll('#tblSubs .eBtn').forEach(b=>{
    if (b.dataset.bound) return; b.dataset.bound="1";
    b.addEventListener('click', ()=>{
      const x=JSON.parse(b.closest('tr').dataset.json);
      document.getElementById('eId').value     = x.id;
      document.getElementById('eItemId').value = x.item_id || '';
      document.getElementById('eUserPrev').value = x.username_ref || '';
      document.getElementById('eText').value   = x.text_content || '';
      const info = [];
      info.push(`Status: <b>${esc(x.status)}</b>`);
      if(x.file_path) info.push(`Fayl: <a href="${x.file_path}" target="_blank">ko‘rish</a>`);
      document.getElementById('eInfo').innerHTML = info.join(' • ');
      bootstrap.Modal.getOrCreateInstance(document.getElementById('editModal')).show();
    });
  });
}

async function loadSubs(){
  const ym=elYM.value;
  try{
    const r=await fetch('../api/submissions.php?action=list&ym='+encodeURIComponent(ym));
    const d=await r.json();
    subsState.rows = d.rows || [];
    subsState.page = 1;
    subsState.limit= 10;
    renderSubs();
  }catch(e){ showAlert('Dalillar ro‘yxati xatosi: '+e.message,'danger'); }
}

// Save edit (matn + fayl)
document.getElementById('eSave').addEventListener('click', async ()=>{
  const id = parseInt(document.getElementById('eId').value,10);
  const item_id = parseInt(document.getElementById('eItemId').value||'0',10);
  const ym = elYM.value;
  const newText = document.getElementById('eText').value;
  const prevUser = document.getElementById('eUserPrev').value || '';
  const fileEl = document.getElementById('eFile');
  const newFile = fileEl.files && fileEl.files[0] ? fileEl.files[0] : null;

  if(newFile){
    let fileHash=null, textHash=null;
    try{
      fileHash = await sha256OfFile(newFile);
      if(newText.trim()) textHash = await sha256OfText(newText.trim());
      const chkRes = await fetch('../api/submissions.php?action=check',{
        method:'POST', headers:{'Content-Type':'application/json; charset=utf-8'},
        body: JSON.stringify({ ym, item_id, file_hash:fileHash||'', text_hash:textHash||'' })
      });
      const chk = await chkRes.json();
      if(!chkRes.ok) throw new Error(chk.error||chkRes.statusText);
      if(chk.exists && (chk.status==='approved' || chk.status==='pending')){
        showNotice(`<div>Bu fayl/matn dublikati avval yuborilgan (<b>${esc(chk.status)}</b>).</div>`); return;
      }
    }catch(e){ showNotice(`<div>Dublikat tekshiruvida xato: ${esc(e.message)}</div>`); return; }

    const fd=new FormData();
    fd.append('id', String(id));
    fd.append('ym', ym);
    fd.append('item_id', String(item_id));
    fd.append('text_content', newText);
    fd.append('file', newFile, newFile.name);
    if(fileHash) fd.append('file_hash', fileHash);
    if(textHash) fd.append('text_hash', textHash);

    try{
      const r=await fetch('../api/submissions.php?action=update_file',{method:'POST',body:fd});
      const t=await r.text(); if(!r.ok) throw new Error(`HTTP ${r.status} ${r.statusText} — ${t.slice(0,200)}`);
      const d=JSON.parse(t);
      if(d.ok){ bootstrap.Modal.getOrCreateInstance(document.getElementById('editModal')).hide(); await loadSubs(); }
      else showNotice(`<div>Saqlash xatosi: ${esc(d.error||'')}</div>`);
    }catch(e){ showNotice(`<div>Saqlash xatosi: ${esc(e.message)}</div>`); }
    return;
  }

  try{
    const r=await fetch('../api/submissions.php?action=update',{
      method:'POST', headers:{'Content-Type':'application/json; charset=utf-8'},
      body: JSON.stringify({ id, text_content:newText, username_ref: prevUser })
    });
    const t=await r.text(); if(!r.ok) throw new Error(`HTTP ${r.status} ${r.statusText} — ${t.slice(0,200)}`);
    const d=JSON.parse(t);
    if(d.ok){ bootstrap.Modal.getOrCreateInstance(document.getElementById('editModal')).hide(); await loadSubs(); }
    else showNotice(`<div>Saqlash xatosi: ${esc(d.error||'')}</div>`);
  }catch(e){ showNotice(`<div>Saqlash xatosi: ${esc(e.message)}</div>`); }
});

/* ================= 3) Grafikalar ================= */
let chPie, chBar, chLine;
async function loadCharts(){
  const ym=elYM.value;
  try{
    const r=await fetch('../api/op_stats.php?ym='+encodeURIComponent(ym));
    const s=await r.json();
    const sc  = (s && s.status_counts) ? s.status_counts : {};
    const pi  = Array.isArray(s?.per_item) ? s.per_item : [];
    const pd  = Array.isArray(s?.per_day)  ? s.per_day  : [];
    const pie    = [sc.approved||0, sc.pending||0, sc.rejected||0];
    const labels = pi.map(x=>x.title||'');
    const appr   = pi.map(x=>x.approved||0);
    const pend   = pi.map(x=>x.pending||0);
    const rej    = pi.map(x=>x.rejected||0);
    const days   = pd.map(x=>x.day||'');
    const cnts   = pd.map(x=>x.count||0);
    if(chPie) chPie.destroy(); if(chBar) chBar.destroy(); if(chLine) chLine.destroy();
    chPie = new Chart(document.getElementById('chPie'), { type:'pie', data:{ labels:['Approved','Pending','Rejected'], datasets:[{ data:pie }] } });
    chBar = new Chart(document.getElementById('chBar'), { type:'bar', data:{ labels, datasets:[{label:'Approved',data:appr},{label:'Pending',data:pend},{label:'Rejected',data:rej}] }, options:{ responsive:true, plugins:{legend:{position:'top'}} } });
    chLine= new Chart(document.getElementById('chLine'), { type:'line', data:{ labels:days, datasets:[{label:'Yuborilgan dalillar', data:cnts, tension:.3}] } });
  }catch(e){ showAlert('Grafik xatosi: '+e.message,'danger'); }
}

/* ================= 4) Oylik tasdiqlash: imzo canvasi ================= */
let ctx, drawing=false, lastPoint=null, saveBusy=false;

function resizeCanvasForDPR(canvas, cssHeight=220){
  canvas.style.width = '100%';
  canvas.style.height= cssHeight+'px';
  const rect = canvas.getBoundingClientRect();
  const dpr  = window.devicePixelRatio || 1;
  canvas.width  = Math.max(1, Math.floor(rect.width  * dpr));
  canvas.height = Math.max(1, Math.floor(rect.height * dpr));
  const _ctx = canvas.getContext('2d');
  _ctx.setTransform(dpr,0,0,dpr,0,0);
  _ctx.lineCap='round'; _ctx.lineJoin='round'; _ctx.lineWidth=2; _ctx.strokeStyle='#111';
  return _ctx;
}

function getPoint(e, canvas){
  const r = canvas.getBoundingClientRect();
  let cx, cy;
  if (e.touches && e.touches[0]) { cx=e.touches[0].clientX; cy=e.touches[0].clientY; }
  else if (e.changedTouches && e.changedTouches[0]) { cx=e.changedTouches[0].clientX; cy=e.changedTouches[0].clientY; }
  else { cx=e.clientX; cy=e.clientY; }
  return {x: cx-r.left, y: cy-r.top};
}

function initPad(){
  const c = document.getElementById('signPad');
  ctx = resizeCanvasForDPR(c, 240);

  const drawTo=(x,y)=>{ if(!drawing||lastPoint===null) return; ctx.beginPath(); ctx.moveTo(lastPoint.x,lastPoint.y); ctx.lineTo(x,y); ctx.stroke(); lastPoint={x,y}; };

  const onPointerDown = (e)=>{ e.preventDefault(); drawing=true; c.setPointerCapture?.(e.pointerId); const p=getPoint(e,c); lastPoint={x:p.x,y:p.y}; };
  const onPointerMove = (e)=>{ if(!drawing) return; e.preventDefault(); const p=getPoint(e,c); drawTo(p.x,p.y); };
  const onPointerUp   = (e)=>{ if(!drawing) return; e.preventDefault(); drawing=false; lastPoint=null; };
  c.addEventListener('pointerdown', onPointerDown, {passive:false});
  c.addEventListener('pointermove', onPointerMove, {passive:false});
  c.addEventListener('pointerup',   onPointerUp,   {passive:false});
  c.addEventListener('pointercancel', onPointerUp, {passive:false});
  c.addEventListener('pointerleave',  onPointerUp, {passive:false});

  const onTouchStart=(e)=>{ e.preventDefault(); drawing=true; const p=getPoint(e,c); lastPoint={x:p.x,y:p.y}; };
  const onTouchMove =(e)=>{ if(!drawing) return; e.preventDefault(); const p=getPoint(e,c); drawTo(p.x,p.y); };
  const onTouchEnd  =(e)=>{ e.preventDefault(); drawing=false; lastPoint=null; };
  c.addEventListener('touchstart', onTouchStart, {passive:false});
  c.addEventListener('touchmove',  onTouchMove,  {passive:false});
  c.addEventListener('touchend',   onTouchEnd,   {passive:false});
  c.addEventListener('touchcancel',onTouchEnd,   {passive:false});

  const onMouseDown=(e)=>{ e.preventDefault(); drawing=true; const p=getPoint(e,c); lastPoint={x:p.x,y:p.y}; };
  const onMouseMove=(e)=>{ if(!drawing) return; e.preventDefault(); const p=getPoint(e,c); drawTo(p.x,p.y); };
  const onMouseUp  =()=>{ drawing=false; lastPoint=null; };
  c.addEventListener('mousedown', onMouseDown, {passive:false});
  window.addEventListener('mousemove', onMouseMove, {passive:false});
  window.addEventListener('mouseup',   onMouseUp,   {passive:false});

  document.getElementById('btnClearSign').onclick=()=>{ ctx.clearRect(0,0,c.width,c.height); };

  document.getElementById('btnSaveSign').onclick=async ()=>{
    if(saveBusy) return; saveBusy=true;
    try{
      const ym=elYM.value; const dataURL=c.toDataURL('image/png');
      const res=await fetch('../api/signoff.php?action=sign',{method:'POST',headers:{'Content-Type':'application/json; charset=utf-8'},body:JSON.stringify({ym,dataURL})});
      const t=await res.text(); if(!res.ok) throw new Error(`HTTP ${res.status} ${res.statusText} — ${t.slice(0,200)}`);
      const d=JSON.parse(t);
      if(d.ok){ await loadSalary(); showNotice('<div>Imzo saqlandi.</div>'); }
      else    { throw new Error(d.detail? (d.error+' — '+d.detail) : JSON.stringify(d)); }
    }catch(e){ showAlert('Imzo saqlash xatosi: '+e.message,'danger'); }
    finally{ saveBusy=false; }
  };

  const rescale=()=>{
    const imgData=c.toDataURL('image/png');
    ctx = resizeCanvasForDPR(c, 240);
    const img=new Image(); img.onload=()=>{ ctx.drawImage(img,0,0,c.width,c.height); }; img.src=imgData;
  };
  window.addEventListener('resize', rescale, {passive:true});
  window.addEventListener('orientationchange', rescale, {passive:true});

  c.dataset.init = 1;
}

/* ================= 4) Salary (imzo holatiga qarab UI) ================= */
async function loadSalary(){
  const ym=elYM.value;

  let plansJson=null, subJson=null, brJson=null;
  try{ plansJson = await (await fetch('../api/op_my_plans.php?ym='+encodeURIComponent(ym))).json(); }catch(e){}
  try{ subJson   = await (await fetch('../api/submissions.php?action=list&ym='+encodeURIComponent(ym))).json(); }catch(e){}
  try{ brJson    = await (await fetch('../api/op_salary_breakdown.php?ym='+encodeURIComponent(ym))).json(); }catch(e){}

  const approvedByItem=new Map();
  (subJson?.rows||[]).forEach(r=>{
    if(r.status!=='approved') return;
    const key = (typeof r.item_id!=='undefined' && r.item_id!==null) ? String(r.item_id) : 't:'+String(r.item_title||'').toLowerCase();
    approvedByItem.set(key,(approvedByItem.get(key)||0)+1);
  });

  const details=[]; let totalBonus=0;
  const plans = plansJson?.plans || [];
  for(const p of plans){
    const planName = p?.plan?.name ?? p?.plan_name ?? '';
    for(const it of (p.items||[])){
      const itemKey  = (typeof it.id!=='undefined' && it.id!==null) ? String(it.id) : 't:'+String(it.title||'').toLowerCase();
      const approved = approvedByItem.get(itemKey)||0;
      const target   = Number(it.target_int||0);
      const rawPct   = target>0 ? (approved/target) : 0;

      const rewardAmount = Number(it.reward_amount||0);
      const mode         = (it.reward_calc||'proportional').toLowerCase();
      let   minPct       = Number(it.reward_min_pct||0); if(minPct>1) minPct=minPct/100;
      const allowOver    = (Number(it.reward_allow_over||0)===1);

      const pctForPay = allowOver ? rawPct : Math.min(rawPct,1);
      let payout=0;
      if(mode==='threshold'){ payout = (rawPct>=minPct) ? rewardAmount : 0; }
      else { payout = (rawPct>=minPct) ? (rewardAmount*pctForPay) : 0; }
      payout=Math.round(payout);

      totalBonus += payout;
      details.push({ plan_name:planName, title:it.title||'', target, approved, pct:rawPct, rewardAmount, mode, minPct, allowOver, payout });
    }
  }

  const br = brJson?.breakdown || {};
  const adminFinal    = !!(br.admin_finalized ?? br.finalized ?? false);
  const operatorSigned= !!(br.operator_signed ?? br.signed ?? false);
  const operatorSignedAt = br.operator_signed_at || br.signed_at || '';
  const signaturePath = br.operator_signature_path || br.signature_path || null;

  const base      = Number(br.base_amount ?? br.base ?? 0);
  let   penalties = Number(br.penalties_total ?? br.penalties ?? 0);
  const penaltiesList = Array.isArray(br.penalties_list) ? br.penalties_list : [];
  if (!isFinite(penalties) && penaltiesList.length) {
    penalties = penaltiesList.reduce((s,x)=> s + Number(x.amount||0), 0);
  }
  const net = (br.net != null) ? Number(br.net) : (base + totalBonus - penalties);

  const adminBadge    = adminFinal ? '<span class="badge text-bg-success">Tasdiqlangan</span>' : '<span class="badge text-bg-warning text-dark">Kutilmoqda</span>';
  const operatorBadge = operatorSigned ? '<span class="badge text-bg-success">Imzolangan</span>' : '<span class="badge text-bg-warning text-dark">Kutilmoqda</span>';

  const rows = details.map(d=>`
    <tr>
      <td><div class="fw-semibold">${esc(d.title)}</div><div class="text-muted small">${esc(d.plan_name)}</div></td>
      <td class="text-center">${d.target}</td>
      <td class="text-center">${d.approved}</td>
      <td class="text-center">${toPct(d.pct)}</td>
      <td>${esc(d.mode)}<div class="text-muted small">min: ${toPct(d.minPct)}${d.allowOver?' • 100%+':''}</div></td>
      <td class="text-end">${fmtUZS(d.rewardAmount)}</td>
      <td class="text-end fw-semibold">${fmtUZS(d.payout)}</td>
    </tr>`).join('');

  const penRows = (penaltiesList.length ? penaltiesList.map(p=>`
      <tr><td>${esc(p.reason||'-')}</td><td class="text-end">${fmtUZS(p.amount||0)}</td></tr>
    `).join('') : '<tr><td class="text-muted">Jarima yo‘q</td><td class="text-end">0 so\'m</td></tr>');

  const box=document.getElementById('salaryBox');
  box.innerHTML = `
    <div class="card mb-3">
      <div class="card-header bg-light fw-semibold">Yakuniy hisob (dinamik)</div>
      <div class="card-body">
        <div class="row g-2">
          <div class="col-md-3"><div class="border rounded p-2">
            <div class="text-muted small">Admin holati</div>
            <div>${adminBadge}</div>
          </div></div>
          <div class="col-md-3"><div class="border rounded p-2">
            <div class="text-muted small">Operator imzosi</div>
            <div>${operatorBadge}${operatorSignedAt? `<div class="text-muted small mt-1">${esc(operatorSignedAt)}</div>`:''}</div>
          </div></div>
          <div class="col-md-3"><div class="border rounded p-2">
            <div class="text-muted small">Asosiy oylik</div>
            <div class="fs-5">${fmtUZS(base)}</div>
          </div></div>
          <div class="col-md-3"><div class="border rounded p-2">
            <div class="text-muted small">Bonuslar (hisoblangan)</div>
            <div class="fs-5">${fmtUZS(totalBonus)}</div>
          </div></div>
        </div>

        <div class="row g-2 mt-2">
          <div class="col-md-6">
            <div class="border rounded p-2">
              <div class="text-muted small">Jarimalar</div>
              <div class="table-responsive"><table class="table table-sm mb-2">
                <tbody>${penRows}</tbody>
                <tfoot><tr><th>Jami</th><th class="text-end">${fmtUZS(penalties)}</th></tr></tfoot>
              </table></div>
            </div>
          </div>
          <div class="col-md-6">
            <div class="border rounded p-2 h-100">
              <div class="text-muted small">NET</div>
              <div class="fs-3">${fmtUZS(net)}</div>
            </div>
          </div>
        </div>

        <div class="table-responsive mt-3">
          <table class="table table-sm align-middle">
            <thead class="table-light">
              <tr>
                <th>Punkt</th><th class="text-center">Plan</th><th class="text-center">Tasdiqlangan</th>
                <th class="text-center">% (approved/plan)</th><th>Usul</th><th class="text-end">Mukofot</th><th class="text-end">Hisoblangan</th>
              </tr>
            </thead>
            <tbody>${rows || '<tr><td colspan="7" class="text-muted">Punktlar topilmadi</td></tr>'}</tbody>
          </table>
        </div>

        ${!adminFinal ? `<div class="alert alert-info mt-2">Admin hali bu oy uchun hisobni <strong>tasdiqlamagan</strong>. Tasdiqlangach, imzo qo‘yishingiz mumkin.</div>`:''}
      </div>
    </div>`;

  const signBox   = document.getElementById('signBox');
  const signedInfo= document.getElementById('signedInfo');

  if (adminFinal) {
    if (operatorSigned) {
      signBox.classList.add('d-none');
      signedInfo.classList.remove('d-none');
      const sigSrc = signaturePath ? (signaturePath+'?v='+(encodeURIComponent(operatorSignedAt||Date.now()))) : null;
      signedInfo.innerHTML = `
        <div class="alert alert-success">Siz ${esc(operatorSignedAt||'')} da imzo qo‘ygansiz.</div>
        ${sigSrc?`<div><img src="/oylik2/public${sigSrc}" class="img-fluid" style="max-width:360px"></div>`:''}`;
    } else {
      signedInfo.classList.add('d-none');
      signBox.classList.remove('d-none');
      const c = document.getElementById('signPad');
      if(!c.dataset.init){ initPad(); c.dataset.init=1; }
    }
  } else {
    signBox.classList.add('d-none');
    signedInfo.classList.add('d-none');
  }
}

// init
document.getElementById('btnReload').addEventListener('click', reloadAll);
window.addEventListener('DOMContentLoaded', reloadAll);

// Tab 4 ochilganda DPI qayta moslash
document.getElementById('t4-tab').addEventListener('shown.bs.tab', ()=>{
  const c=document.getElementById('signPad');
  if(c && c.dataset.init){
    const imgData=c.toDataURL('image/png');
    ctx = (function(canvas, cssH){ 
      canvas.style.width='100%'; canvas.style.height=cssH+'px';
      const rect=canvas.getBoundingClientRect(), dpr=window.devicePixelRatio||1;
      canvas.width=Math.max(1, Math.floor(rect.width*dpr)); canvas.height=Math.max(1, Math.floor(rect.height*dpr));
      const _ctx=canvas.getContext('2d'); _ctx.setTransform(dpr,0,0,dpr,0,0); _ctx.lineCap='round'; _ctx.lineJoin='round'; _ctx.lineWidth=2; _ctx.strokeStyle='#111';
      return _ctx;
    })(c,240);
    const img=new Image(); img.onload=()=>{ ctx.drawImage(img,0,0,c.width,c.height); }; img.src=imgData;
  }
});
</script>
</body>
</html>
