/**
 * Shared final report table + print header/footer rendering.
 * Lives in Reports/; loaded by admin.html and employee-final-report-print.html
 */
(function (global) {
  'use strict';

  function lsBuildEditForDay(day) {
    if (day.manager_edit && day.manager_edit.leave_type && Number(day.manager_edit.days) > 0) {
      return {
        leave_type: day.manager_edit.leave_type,
        days: Number(day.manager_edit.days),
        reason: day.manager_edit.reason || ''
      };
    }
    if (day.system_settlement) {
      return {
        leave_type: day.system_settlement.leave_type,
        days: Number(day.system_settlement.days),
        reason: ''
      };
    }
    const mds = day.manual_deductions || [];
    if (mds.length === 1) {
      return { leave_type: mds[0].leave_type, days: Number(mds[0].days), reason: (mds[0].reason && String(mds[0].reason)) || '' };
    }
    if (mds.length > 1) {
      const by = {};
      mds.forEach((m) => {
        const lt = m.leave_type;
        by[lt] = (by[lt] || 0) + Number(m.days);
      });
      const keys = Object.keys(by);
      if (keys.length === 1) return { leave_type: keys[0], days: by[keys[0]], reason: '' };
      return { leave_type: mds[0].leave_type, days: Number(mds[0].days), reason: '' };
    }
    if (day.can_manual_deduct) return { leave_type: 'annual', days: '', reason: '' };
    return null;
  }

  function formatLeaveBalanceBox(b) {
    if (!b) return '0 / 0';
    const rem = Number(b.rem);
    const tot = Number(b.total);
    const remStr = Math.abs(rem - Math.round(rem)) < 0.001 ? String(Math.round(rem)) : rem.toFixed(2);
    return `${remStr} / ${tot}`;
  }

  function getT(options) {
    if (options && typeof options.t === 'function') return options.t;
    if (typeof global.hrproFinalReportT === 'function') return global.hrproFinalReportT;
    return function (k) { return k; };
  }

  /**
   * @param {object} data - API reports/final payload
   * @param {object} [options]
   * @param {'admin'|'print'} [options.mode='admin']
   * @param {boolean} [options.omitSettlementColumn=false]
   * @param {string} [options.hideMode] - override finalReportHideDays select
   * @param {string} [options.fromStr]
   * @param {string} [options.toStr]
   * @param {string} [options.employeeDisplayName]
   * @param {function(string):string} [options.t]
   */
  function renderFinalReport(data, options) {
    options = options || {};
    const t = getT(options);
    const mode = options.mode === 'print' ? 'print' : 'admin';
    const omitSettlementColumn = !!options.omitSettlementColumn;
    /* Print page: 11 cols — date+day merged, no notes; admin: 14 with notes + settlement */
    const cc = omitSettlementColumn ? 11 : 14;

    const escHtml = (s) => {
      if (s == null || s === '') return '';
      return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
    };

    const tbody = document.getElementById('finalReportTable');
    if (!tbody) return;

    const reportAll = data.report || [];
    const hideMode = options.hideMode != null
      ? options.hideMode
      : (document.getElementById('finalReportHideDays')?.value || 'all');
    const rowVisible = (r) => {
      const st = r.status || '';
      if (hideMode === 'hide_weekend') return st !== 'weekend';
      if (hideMode === 'hide_official') return st !== 'official_holiday';
      if (hideMode === 'hide_both') return st !== 'weekend' && st !== 'official_holiday';
      return true;
    };
    const report = reportAll.filter(rowVisible);
    const balances = data.balances || {};
    const policy = data.policy || {};
    const profile = data.employee_profile || {};
    const totals = data.totals || {};

    const win = typeof window !== 'undefined' ? window : global;
    if (mode === 'admin') {
      win._frDeductFractions = (policy.deduct_options && policy.deduct_options.length)
        ? policy.deduct_options
        : [1, 0.5, 0.25];
      win._frPolicySalary = {
        allow_with_balance: parseInt(String(policy.salary_deduct_allow_with_balance ?? 0), 10) === 1,
        balance_exhausted: !!policy._balance_exhausted
      };
      if (Array.isArray(data.suggestion_codes) && data.suggestion_codes.length) {
        win._frSuggestionCodes = data.suggestion_codes;
      }

      win._frSettlementEdits = {};
      (reportAll || []).forEach((row) => {
        const ed = lsBuildEditForDay(row);
        if (ed) win._frSettlementEdits[row.date] = ed;
      });
      const polBan = document.getElementById('frSettlementPolicyBanner');
      if (polBan) {
        polBan.style.display = data.policy_missing ? 'block' : 'none';
      }
      if (typeof win.frUpdateTableDensity === 'function') {
        win.frUpdateTableDensity();
      }
    }

    let present = 0;
    let absent = 0;
    let leave = 0;
    let officialH = 0;
    if (report && report.length) {
      report.forEach((r) => {
        if (r.status === 'present') present++;
        else if (r.status === 'leave') leave++;
        else if (r.status === 'official_holiday') officialH++;
        else if (r.status === 'absent') absent++;
      });
    }

    const fromStr = options.fromStr != null
      ? options.fromStr
      : (document.getElementById('finalReportFrom')?.value || '');
    const toStr = options.toStr != null
      ? options.toStr
      : (document.getElementById('finalReportTo')?.value || '');

    const sel = document.getElementById('finalReportEmployee');
    let empLine = '';
    if (options.employeeDisplayName != null && String(options.employeeDisplayName) !== '') {
      empLine = String(options.employeeDisplayName);
      const pen = document.getElementById('printEmpName');
      if (pen) pen.textContent = empLine;
    } else if (sel && sel.selectedIndex >= 0) {
      empLine = sel.options[sel.selectedIndex].text || '';
      const pen = document.getElementById('printEmpName');
      if (pen) pen.textContent = empLine;
    }

    const printPeriod = document.getElementById('printPeriod');
    if (printPeriod) printPeriod.textContent = fromStr + ' → ' + toStr;

    const metaEl = document.getElementById('finalReportEmpMeta');
    if (metaEl) {
      const natureLabel = profile.work_nature === 'external' ? t('external') : t('internal');
      metaEl.innerHTML = `
      <div><strong>${t('department')}:</strong> ${escHtml(profile.department) || '—'}</div>
      <div><strong>${t('branch')}:</strong> ${escHtml(profile.branch) || '—'}</div>
      <div><strong>${t('job_title')}:</strong> ${escHtml(profile.job_title) || '—'}</div>
      <div><strong>${t('code')}:</strong> <span style="font-family:var(--mono)">${escHtml(profile.employee_code) || '—'}</span></div>
      <div><strong>${t('work_nature')}:</strong> ${escHtml(natureLabel)}</div>
      <div><strong>${t('fr_policy')}:</strong> ${escHtml(profile.policy_name) || '—'}</div>
      ${data.balance_year != null ? `<div><strong>${t('fr_balance_year')}:</strong> ${data.balance_year}</div>` : ''}
      ${profile.phone ? `<div><strong>${t('phone')}:</strong> <span dir="ltr">${escHtml(profile.phone)}</span></div>` : ''}
      ${profile.email ? `<div><strong>${t('email')}:</strong> ${escHtml(profile.email)}</div>` : ''}
    `;
    }

    const setNum = (id, val) => {
      const el = document.getElementById(id);
      if (el) el.textContent = val;
    };
    setNum('printTotalPresent', present);
    setNum('printTotalAbsent', absent);
    setNum('printTotalLeave', leave);
    const poh = document.getElementById('printTotalOfficialHoliday');
    if (poh) poh.textContent = officialH;

    if (balances.annual) setNum('printAnnualRem', formatLeaveBalanceBox(balances.annual));
    if (balances.casual) setNum('printCasualRem', formatLeaveBalanceBox(balances.casual));
    if (balances.sick) setNum('printSickRem', formatLeaveBalanceBox(balances.sick));

    const langDoc = document.documentElement.lang || 'ar';
    const thWh = document.getElementById('printTotalWorkHours');
    if (thWh) {
      thWh.textContent = (totals.work_hours_sum != null ? totals.work_hours_sum : 0)
        + (langDoc === 'ar' ? ' س' : ' h');
    }
    setNum('printLateDaysCount', totals.late_days != null ? totals.late_days : 0);
    setNum('printEarlyLeaveCount', totals.early_out_days != null ? totals.early_out_days : 0);
    setNum('printAlertDaysCount', totals.location_alert_days != null ? totals.location_alert_days : 0);
    setNum('printIncompleteDaysCount', totals.incomplete_days != null ? totals.incomplete_days : 0);
    const tsd = document.getElementById('printSalaryDeductDays');
    if (tsd) tsd.textContent = totals.salary_deduction_days != null ? String(totals.salary_deduction_days) : '0';

    const pgd = document.getElementById('printGenerationDate');
    if (pgd) pgd.textContent = new Date().toLocaleString();

    const stripEl = document.getElementById('frScreenContextStrip');
    if (stripEl && mode === 'admin') {
      if (!reportAll || !reportAll.length) {
        stripEl.innerHTML = '';
      } else {
        stripEl.innerHTML = `<div><strong>${escHtml(empLine)}</strong> · <span style="font-family:var(--mono);">${escHtml(fromStr)} → ${escHtml(toStr)}</span></div>`
          + `<div style="margin-top:6px;font-size:12px;">${escHtml(t('status_present'))}: ${present} · ${escHtml(t('status_absent'))}: ${absent} · ${escHtml(t('status_leave'))}: ${leave} · ${escHtml(t('status_official_holiday'))}: ${officialH} · `
          + `${escHtml(t('annual'))} ${escHtml(formatLeaveBalanceBox(balances.annual || {}))} · ${escHtml(t('casual'))} ${escHtml(formatLeaveBalanceBox(balances.casual || {}))} · ${escHtml(t('sick'))} ${escHtml(formatLeaveBalanceBox(balances.sick || {}))}</div>`;
      }
    }

    const cname = (typeof localStorage !== 'undefined' && localStorage.getItem('admin_company_name')) || '';
    const setFoot = (id, v) => {
      const el = document.getElementById(id);
      if (el) el.textContent = v != null && String(v) !== '' ? String(v) : '—';
    };
    setFoot('frPrintCompanyName', cname || '—');
    setFoot('frPrintFooterEmpName', profile.name || empLine);
    setFoot('frPrintFooterCode', profile.employee_code);
    setFoot('frPrintFooterDept', profile.department);
    setFoot('frPrintFooterBranch', profile.branch);
    setFoot('frPrintFooterPolicy', profile.policy_name);
    setFoot('frPrintFooterBalYear', data.balance_year != null ? String(data.balance_year) : '');
    setFoot('frPrintFooterPeriod', `${fromStr} → ${toStr}`);
    const sumFoot = document.getElementById('frPrintFooterSummary');
    if (sumFoot) {
      if (!reportAll || !reportAll.length) sumFoot.textContent = '—';
      else {
        sumFoot.textContent = `${t('status_present')}: ${present} · ${t('status_absent')}: ${absent} · ${t('status_leave')}: ${leave} · ${t('status_official_holiday')}: ${officialH} · ${t('fr_total_hours')}: ${totals.work_hours_sum != null ? totals.work_hours_sum : 0}`;
      }
    }

    if (!reportAll || !reportAll.length) {
      tbody.innerHTML = `<tr><td colspan="${cc}" style="text-align:center;padding:30px;color:var(--text-muted);">${t('no_records')}</td></tr>`;
      return;
    }
    if (!report.length) {
      tbody.innerHTML = `<tr><td colspan="${cc}" style="text-align:center;padding:30px;color:var(--text-muted);">${t('fr_hide_days_empty') || 'No rows match the current hide filter.'}</td></tr>`;
      return;
    }

    const lang = document.documentElement.lang || 'ar';
    const dayNames = lang === 'ar'
      ? ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت']
      : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

    const locLabel = (st) => (st === 'alert'
      ? `<span style="color:var(--danger);font-weight:700;">${t('fr_loc_alert')}</span>`
      : `<span style="color:var(--success);">${t('fr_loc_ok')}</span>`);
    const fmtDist = (m) => (m != null && m !== '' ? `${Math.round(Number(m))}m` : '—');
    const regLabel = (m) => {
      if (m === 'qr') return t('fr_reg_qr');
      if (m === 'manual') return t('fr_reg_manual');
      return t('fr_reg_direct');
    };
    const dayTypeLabel = (r) => {
      if (r.status !== 'present') return '—';
      return r.logged_work_nature === 'external' ? t('external') : t('internal');
    };

    tbody.innerHTML = report.map((r, idx) => {
      const seq = idx + 1;
      const d = new Date(r.date + 'T12:00:00');
      const dayName = dayNames[d.getDay()];
      let statusBadge = '';
      const notesRaw = r.note || '';

      if (r.status === 'present') {
        statusBadge = `<span class="badge badge-ok">${t('status_present')}</span>`;
      } else if (r.status === 'leave') {
        statusBadge = `<span class="badge badge-pending">${t('status_leave')}</span>`;
      } else if (r.status === 'weekend') {
        statusBadge = `<span class="badge" style="background:var(--surface2); color:var(--textM);">${t('weekend_days') || 'Weekend'}</span>`;
      } else if (r.status === 'official_holiday') {
        statusBadge = `<span class="badge" style="background:rgba(6,182,212,0.12);color:var(--accent);font-weight:600;">${t('status_official_holiday')}</span>`;
      } else {
        statusBadge = `<span class="badge badge-rejected">${t('status_absent')}</span>`;
      }

      const checkInTime = r.check_in ? r.check_in.substring(11, 16) : null;
      const checkOutTime = r.check_out ? r.check_out.substring(11, 16) : null;
      const schIn = r.sch_in ? String(r.sch_in).substring(0, 5) : '09:00';
      const schOut = r.sch_out ? String(r.sch_out).substring(0, 5) : '17:00';

      const isLate = checkInTime && checkInTime > schIn;
      const isEarly = checkOutTime && checkOutTime < schOut;

      const wh = r.work_hours != null ? String(r.work_hours) : '—';

      let locCell = '—';
      if (r.status === 'present') {
        const inS = r.in_location_status || 'ok';
        const outS = r.out_location_status || (r.check_out ? 'ok' : '—');
        const inPart = `${t('first_in')}: ${locLabel(inS)} ${fmtDist(r.in_distance_m)}`;
        const outPart = r.check_out
          ? ` · ${t('last_out')}: ${locLabel(outS)} ${fmtDist(r.out_distance_m)}`
          : '';
        locCell = `<span style="font-size:11px;line-height:1.5;">${inPart}${outPart}</span>`;
      }

      let selfieCell = '—';
      if (r.status === 'present') {
        const a = r.has_selfie_in ? '✓' : '—';
        const b = r.has_selfie_out ? '✓' : '—';
        selfieCell = `<span style="font-family:var(--mono);font-size:12px;" title="${t('first_in')}/${t('last_out')}">${a} / ${b}</span>`;
      }

      const methodCell = r.status === 'present' ? `<span style="font-size:12px;">${regLabel(r.registration_method)}</span>` : '—';
      const dayTypeCell = dayTypeLabel(r);

      const mdList = r.manual_deductions || [];
      const salList = r.salary_deductions || [];

      let deductCell = '';
      if (!omitSettlementColumn) {
        let deductInner = '';
        if (mdList.length) {
          deductInner = mdList.map((m) => {
            const delBtn = `<button type="button" class="btn btn-sm btn-outline-danger fr-no-print" style="min-width:auto;padding:4px 8px;font-size:11px;" data-fr-deduct-del="${m.id}">${escHtml(t('dr_revert'))}</button>`;
            return `<div style="font-size:11px;display:flex;align-items:flex-start;gap:6px;justify-content:space-between;border-bottom:1px solid var(--border);padding:4px 0;"><span><span style="font-weight:700;">${t(m.leave_type)}</span> −${m.days}${m.reason ? ' · ' + escHtml(m.reason) : ''}</span>${delBtn}</div>`;
          }).join('');
        } else {
          deductInner = `<span style="color:var(--textM);font-size:11px;">—</span>`;
        }
        if (r.can_manual_deduct) {
          deductInner += `<div class="fr-no-print" style="margin-top:8px;"><button type="button" class="btn btn-sm btn-secondary" data-fr-deduct-date="${r.date}">${t('fr_deduct_btn')}</button></div>`;
        }
        let salaryInner = '';
        if (salList.length) {
          salaryInner = salList.map((s) => {
            const forceNote = parseInt(String(s.force_despite_balance ?? 0), 10) === 1 ? ` · ${t('fr_salary_force_tag')}` : '';
            const delSal = `<button type="button" class="btn btn-sm btn-outline-danger fr-no-print" style="min-width:auto;padding:4px 8px;font-size:11px;" data-fr-salary-del="${s.id}">${escHtml(t('dr_revert'))}</button>`;
            return `<div style="font-size:11px;display:flex;align-items:flex-start;gap:6px;justify-content:space-between;border-bottom:1px solid var(--border);padding:4px 0;"><span><span style="font-weight:700;">${t('fr_salary_short')}</span> −${s.days}${forceNote}${s.reason ? ' · ' + escHtml(s.reason) : ''}</span>${delSal}</div>`;
          }).join('');
        }
        if (r.can_mark_salary_deduct) {
          salaryInner += `<div class="fr-no-print" style="margin-top:8px;"><button type="button" class="btn btn-sm btn-outline" data-fr-salary-date="${r.date}">${t('fr_salary_btn')}</button></div>`;
        }
        const salaryBlock = (salList.length || r.can_mark_salary_deduct)
          ? `<div style="margin-top:10px;padding-top:8px;border-top:1px dashed var(--border);"><div style="font-size:10px;font-weight:700;color:var(--textM);text-transform:uppercase;letter-spacing:0.03em;margin-bottom:4px;">${t('fr_salary_section')}</div>${salaryInner || `<span style="color:var(--textM);font-size:11px;">—</span>`}</div>`
          : '';
        const sugList = r.suggestions || [];
        const sugHtml = sugList.length
          ? `<div class="fr-sug-wrap" style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px;" title="${escHtml(t('fr_suggestions_hint'))}">${sugList.map((c) => `<span class="fr-sug-chip">${escHtml(t('fr_sug_' + c))}</span>`).join('')}</div>`
          : '';
        const lp = r.late_leave_deduct_preview;
        const lateRowBtn = (lp && lp.days && !(r.manual_deductions || []).length)
          ? `<div class="fr-no-print" style="margin-top:6px;"><button type="button" class="btn btn-sm btn-outline-accent" data-fr-late-apply="${escHtml(r.date)}" title="${escHtml(String(lp.late_minutes))} min → ${escHtml(String(lp.days))} d">${escHtml(t('fr_apply_late_row'))}</button></div>`
          : '';
        let sysLine = '';
        if (r.system_settlement) {
          const ss = r.system_settlement;
          sysLine = `<div class="fr-no-print" style="font-size:11px;color:var(--accent);margin-bottom:6px;line-height:1.4;"><strong>${escHtml(t('ls_col_system'))}:</strong> ${escHtml(t(ss.leave_type))} ${escHtml(String(ss.days))} — ${escHtml(ss.reason_text || ss.reason_code || '')}</div>`;
        }
        const w = typeof window !== 'undefined' ? window : global;
        const editFr = w._frSettlementEdits && w._frSettlementEdits[r.date];
        let settleEditHtml = '';
        if (editFr) {
          const fracs = w._frDeductFractions || [1, 0.5, 0.25];
          const ltSel = ['annual', 'casual', 'sick'].map((lt) =>
            `<option value="${lt}" ${editFr.leave_type === lt ? 'selected' : ''}>${escHtml(t(lt))}</option>`
          ).join('');
          const dayOpts = ['<option value="">—</option>'].concat(fracs.map((f) => {
            const fv = (Math.abs(f - Math.round(f)) < 0.001) ? String(Math.round(f)) : String(f);
            const cur = editFr.days === '' || editFr.days == null ? NaN : Number(editFr.days);
            const sopt = Number.isFinite(cur) && Math.abs(cur - f) < 0.001 ? 'selected' : '';
            return `<option value="${fv}" ${sopt}>${fv}</option>`;
          })).join('');
          const resetB = r.system_settlement
            ? `<button type="button" class="btn btn-sm btn-ghost fr-no-print" data-fr-slt-reset="${escHtml(r.date)}">${escHtml(t('ls_reset_row'))}</button>`
            : '';
          settleEditHtml = `<div class="fr-settle-edit fr-no-print" style="margin-top:8px;padding-top:8px;border-top:1px dashed var(--border);">
        <div style="font-size:10px;font-weight:700;color:var(--accent);margin-bottom:6px;text-transform:uppercase;letter-spacing:0.03em;">${escHtml(t('fr_settlement_editor'))}</div>
        <div style="display:flex;flex-wrap:wrap;gap:8px;align-items:center;">
          <select class="input fr-slt-type" style="min-width:100px;padding:6px;" data-fr-slt="${escHtml(r.date)}">${ltSel}</select>
          <select class="input fr-slt-days" style="min-width:80px;padding:6px;" data-fr-slt="${escHtml(r.date)}">${dayOpts}</select>
          <input type="text" class="input fr-slt-reason" style="flex:1;min-width:120px;padding:6px;" data-fr-slt="${escHtml(r.date)}" value="${escHtml(editFr.reason || '')}" maxlength="500" />
          ${resetB}
        </div></div>`;
        }
        deductCell = `<div style="min-width:120px;">${sysLine}${settleEditHtml}${sugHtml}${lateRowBtn}${deductInner}${salaryBlock}</div>`;
      }

      const leaveDetailsPrint = (mdList || []).map((m) =>
        `${escHtml(t(m.leave_type))} −${escHtml(String(m.days))}`
      ).join(` ${t('fr_print_sep')} `);
      const salDetailsPrint = (salList || []).map((s) => {
        const dStr = escHtml(String(s.days ?? ''));
        const rsn = s.reason ? escHtml(String(s.reason)) : '';
        return rsn ? `−${dStr} (${rsn})` : `−${dStr}`;
      }).join(` ${t('fr_print_sep')} `);
      const printDeductParts = [];
      if (mdList.length) {
        printDeductParts.push(`<div><span style="font-weight:700;">${escHtml(t('fr_print_caption_leave'))}:</span> ${leaveDetailsPrint}</div>`);
      }
      if (salList.length) {
        printDeductParts.push(`<div><span style="font-weight:700;">${escHtml(t('fr_print_caption_salary'))}:</span> ${salDetailsPrint}</div>`);
      }
      const printDayDeductInline = printDeductParts.length
        ? `<div class="fr-print-day-deduct-inline">${printDeductParts.join('')}</div>`
        : '';

      const lastCol = omitSettlementColumn
        ? ''
        : `<td class="fr-deduct-cell" data-label="${t('fr_leave_deduct')}">${deductCell}</td>`;

      const dateDayMerged = omitSettlementColumn
        ? `<td class="fr-print-date-day-cell" data-label="${escHtml(t('fr_print_col_date_day'))}" style="vertical-align:top;text-align:center;">
        <span style="color:var(--textM);font-weight:600;margin-inline-end:4px;">${seq}.</span>
        <span style="font-family:var(--mono);font-weight:700;">${r.date}</span>
        <span style="display:block;font-size:11.5px;color:var(--textM);margin-top:4px;font-family:var(--font);">${escHtml(dayName)}</span>
        ${printDayDeductInline}
      </td>`
        : `<td data-label="${t('date')}" style="font-family:var(--mono); font-weight:700;"><span style="color:var(--textM);font-weight:600;margin-inline-end:6px;">${seq}.</span>${r.date}${printDayDeductInline}</td>
        <td data-label="${t('day')}">${dayName}</td>`;

      return `
      <tr>
        ${dateDayMerged}
        <td data-label="${t('fr_work_hours')}" style="font-family:var(--mono);">${wh}</td>
        <td data-label="${t('official_start')}" style="font-family:var(--mono); color:var(--textM); opacity:0.75; font-size:11px;">${schIn}</td>
        <td data-label="${t('first_in')}" style="font-family:var(--mono); color:${isLate ? 'var(--danger)' : 'var(--success)'}; font-weight:700;">
          ${checkInTime || '—'} ${isLate ? '<span style="cursor:help;" title="Late">⚠</span>' : ''}
        </td>
        <td data-label="${t('official_end')}" style="font-family:var(--mono); color:var(--textM); opacity:0.75; font-size:11px;">${schOut}</td>
        <td data-label="${t('last_out')}" style="font-family:var(--mono); color:${isEarly ? 'var(--danger)' : 'var(--accent)'}; font-weight:700;">
          ${checkOutTime || '—'} ${isEarly ? '<span style="cursor:help;" title="Early leave">⚠</span>' : ''}
        </td>
        <td class="fr-col-detail" data-label="${t('fr_location')}">${locCell}</td>
        <td class="fr-col-detail" data-label="${t('fr_selfie')}">${selfieCell}</td>
        <td class="fr-col-detail" data-label="${t('fr_reg_method')}">${methodCell}</td>
        <td class="fr-col-detail" data-label="${t('fr_field_day')}">${dayTypeCell}</td>
        <td data-label="${t('status')}">${statusBadge}</td>
        ${omitSettlementColumn ? '' : `<td class="fr-col-detail" data-label="${t('notes')}" style="color:var(--textM); font-size:12px;">${escHtml(notesRaw)}</td>`}
        ${lastCol}
      </tr>
    `;
    }).join('');
  }

  global.HRProFinalReport = {
    render: renderFinalReport,
    formatLeaveBalanceBox: formatLeaveBalanceBox,
    lsBuildEditForDay: lsBuildEditForDay
  };
})(typeof window !== 'undefined' ? window : self);
