// daily-work-report.js - 브라우저 호환 버전

// =================================================================
//  API 설정 (window 객체에서 가져오기)
// =================================================================
// API 설정은 api-config.js에서 window 객체에 설정됨

// 전역 변수 → DailyWorkReportState 프록시 사용 (state.js에서 window 프록시 정의)
// workTypes, workStatusTypes, errorTypes, issueCategories, issueItems,
// workers, projects, selectedWorkers, incompleteTbms, tempDefects,
// dailyIssuesCache, currentTab, currentStep, editingWorkId, workEntryCounter,
// currentDefectIndex, currentEditingField, currentTimeValue,
// selectedWorkplace, selectedWorkplaceName, selectedWorkplaceCategory, selectedWorkplaceCategoryName

// 지도 관련 변수 (프록시 아님)
var mapCanvas = null;
var mapCtx = null;
var mapImage = null;
var mapRegions = [];

// 시간 선택 관련 변수
// currentEditingField, currentTimeValue → DailyWorkReportState 프록시 사용

// 당일 신고 리마인더 관련 변수
// dailyIssuesCache → DailyWorkReportState 프록시 사용

// =================================================================
// TBM 작업보고 관련 함수
// =================================================================

/**
 * 탭 전환 함수
 */
window.switchTab = function(tab) {
  currentTab = tab;
  const tbmBtn = document.getElementById('tbmReportTab');
  const completedBtn = document.getElementById('completedReportTab');
  const tbmSection = document.getElementById('tbmReportSection');
  const completedSection = document.getElementById('completedReportSection');

  // 모든 탭 버튼 비활성화
  tbmBtn.classList.remove('active');
  completedBtn.classList.remove('active');

  // 모든 섹션 숨기기
  tbmSection.style.display = 'none';
  completedSection.style.display = 'none';

  // 선택된 탭 활성화
  if (tab === 'tbm') {
    tbmBtn.classList.add('active');
    tbmSection.style.display = 'block';
    loadIncompleteTbms(); // TBM 목록 로드
  } else if (tab === 'completed') {
    completedBtn.classList.add('active');
    completedSection.style.display = 'block';

    // 오늘 날짜로 초기화
    document.getElementById('completedReportDate').value = getKoreaToday();
    loadCompletedReports();
  }
};

/**
 * 미완료 TBM 작업 로드
 */
async function loadIncompleteTbms() {
  try {
    const response = await window.apiCall('/tbm/sessions/incomplete-reports');

    if (!response.success) {
      throw new Error(response.message || '미완료 TBM 조회 실패');
    }

    let data = response.data || [];

    // 사용자 권한 확인 및 필터링
    const user = getUser();
    const userRole = (user && user.role || '').toLowerCase();
    const userAccess = (user && user.access_level || '').toLowerCase();
    const isAdmin = userRole === 'admin' || userAccess === 'admin' || userAccess === 'system';
    if (user && !isAdmin) {
      // 일반 사용자: 자신이 생성한 세션만 표시
      const userId = user.user_id;
      data = data.filter(tbm => tbm.created_by === userId);
    }
    // 관리자는 모든 데이터 표시

    incompleteTbms = data;

    // 각 세션 날짜에 대해 관련 신고 조회
    await loadDailyIssuesForTbms();

    renderTbmWorkList();
  } catch (error) {
    console.error('미완료 TBM 로드 오류:', error);
    showMessage('TBM 작업 목록을 불러오는 중 오류가 발생했습니다.', 'error');
  }
}

/**
 * TBM 세션들에 대한 당일 신고 조회
 * - 각 세션 날짜별로 관련 신고를 가져와서 캐시에 저장
 */
async function loadDailyIssuesForTbms() {
  if (!incompleteTbms || incompleteTbms.length === 0) {
    console.log('[작업보고서] 미완료 TBM 없음, 신고 조회 건너뜀');
    return;
  }

  console.log('[작업보고서] TBM 세션 수:', incompleteTbms.length);

  // 세션별로 고유한 날짜 + 작업장 조합 수집
  const sessionKeys = new Set();
  incompleteTbms.forEach(tbm => {
    const dateStr = formatDateForApi(tbm.session_date);
    console.log('[작업보고서] TBM 세션 날짜:', tbm.session_date, '→ 변환:', dateStr);
    if (dateStr) {
      // 날짜_작업장ID_프로젝트ID 형태로 키 생성
      const key = `${dateStr}_${tbm.workplace_id || 0}_${tbm.project_id || 0}`;
      sessionKeys.add(key);
    }
  });

  // 각 날짜에 대해 신고 조회
  const uniqueDates = [...new Set([...sessionKeys].map(k => k.split('_')[0]))];
  console.log('[작업보고서] 조회할 날짜들:', uniqueDates);

  for (const dateStr of uniqueDates) {
    if (dailyIssuesCache[dateStr]) {
      console.log(`[작업보고서] 캐시 사용 (${dateStr}):`, dailyIssuesCache[dateStr].length, '건');
      continue;
    }

    try {
      console.log(`[작업보고서] 신고 API 호출: /work-issues?start_date=${dateStr}&end_date=${dateStr}`);
      const response = await window.apiCall(`/work-issues?start_date=${dateStr}&end_date=${dateStr}`);
      if (response.success) {
        dailyIssuesCache[dateStr] = response.data || [];
        console.log(`[작업보고서] 신고 로드 완료 (${dateStr}):`, dailyIssuesCache[dateStr].length, '건');
      } else {
        console.warn(`[작업보고서] 신고 API 실패:`, response);
        dailyIssuesCache[dateStr] = [];
      }
    } catch (error) {
      console.error(`[작업보고서] 신고 조회 오류 (${dateStr}):`, error);
      dailyIssuesCache[dateStr] = [];
    }
  }

  console.log('[작업보고서] 전체 신고 캐시:', dailyIssuesCache);
}

/**
 * 특정 날짜의 모든 신고 반환 (작업장소 관계없이)
 * - 참고용으로 해당 날짜에 발생한 모든 신고를 표시
 * @param {string} dateStr - 날짜 (YYYY-MM-DD)
 * @param {number} workplaceId - 작업장소 ID (현재 미사용, 향후 하이라이트 용도)
 * @param {number} projectId - 프로젝트 ID (현재 미사용)
 * @returns {Array} 해당 날짜의 모든 신고 목록
 */
function getRelatedIssues(dateStr, workplaceId, projectId) {
  const issues = dailyIssuesCache[dateStr] || [];

  // 해당 날짜의 모든 신고를 반환 (작업장소 필터 제거)
  // 사용자가 참고하여 관련 여부를 직접 판단하도록 함
  return issues;
}

/**
 * 날짜를 API 형식(YYYY-MM-DD)으로 변환
 */
function formatDateForApi(date) {
  if (window.CommonUtils) return window.CommonUtils.formatDate(date) || null;
  if (!date) return null;
  const d = date instanceof Date ? date : new Date(date);
  if (isNaN(d.getTime())) return null;
  return d.getFullYear() + '-' + String(d.getMonth()+1).padStart(2,'0') + '-' + String(d.getDate()).padStart(2,'0');
}

/**
 * 사용자 정보 가져오기 (auth-check.js와 동일한 로직)
 */
function getUser() {
  if (window.getSSOUser) return window.getSSOUser();
  const raw = localStorage.getItem('sso_user');
  try { return raw ? JSON.parse(raw) : null; } catch(e) { return null; }
}

/**
 * TBM 작업 목록 렌더링 (날짜별 > 세션별 그룹화)
 * - 날짜별로 접기/펼치기 가능
 * - 날짜 헤더에 이슈 요약 표시
 */
function renderTbmWorkList() {
  const container = document.getElementById('tbmWorkList');

  // 1단계: 날짜별로 그룹화
  const byDate = {};
  if (incompleteTbms && incompleteTbms.length > 0) {
    incompleteTbms.forEach((tbm, index) => {
      const dateStr = formatDateForApi(tbm.session_date);
      if (!byDate[dateStr]) {
        byDate[dateStr] = {
          date: tbm.session_date,
          sessions: {}
        };
      }
      // 2단계: 날짜 내에서 세션별로 그룹화
      const sessionKey = `${tbm.session_id}_${dateStr}`;
      if (!byDate[dateStr].sessions[sessionKey]) {
        byDate[dateStr].sessions[sessionKey] = {
          session_id: tbm.session_id,
          session_date: tbm.session_date,
          created_by_name: tbm.leader_name || tbm.created_by_name || '-',
          items: []
        };
      }
      byDate[dateStr].sessions[sessionKey].items.push({ ...tbm, originalIndex: index });
    });
  }

  // 날짜 정렬 (최신순)
  const sortedDates = Object.keys(byDate).sort((a, b) => new Date(b) - new Date(a));

  // 레거시 호환: 기존 groupedTbms 구조도 유지
  const groupedTbms = {};
  sortedDates.forEach(dateStr => {
    Object.assign(groupedTbms, byDate[dateStr].sessions);
  });

  let html = `
    <div style="margin-bottom: 1rem; display: flex; justify-content: space-between; align-items: center;">
      <h3 style="margin: 0;">작업보고서 목록</h3>
      <button type="button" class="btn-add-work" onclick="addManualWorkRow()">
         작업 추가
      </button>
    </div>
  `;

  // 수동 입력 섹션 먼저 추가 (맨 위)
  html += `
    <div class="tbm-session-group manual-input-section">
      <div class="tbm-session-header" style="background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 0.5rem;">
        <div>
          <span class="tbm-session-badge" style="background-color: #92400e; color: white;">수동 입력</span>
          <span class="tbm-session-info" style="color: white; font-weight: 500;">TBM에 없는 작업을 추가로 입력할 수 있습니다</span>
        </div>
        <button type="button" class="btn-batch-submit" onclick="submitAllManualWorkReports()" style="background: #fff; color: #d97706; border: none; padding: 0.4rem 0.8rem; border-radius: 4px; font-weight: 600; cursor: pointer; font-size: 0.8rem;">
           일괄 제출
        </button>
      </div>
      <div class="tbm-table-container">
        <table class="tbm-work-table">
          <thead>
            <tr>
              <th>작업자</th>
              <th>날짜</th>
              <th>프로젝트</th>
              <th>공정</th>
              <th>작업</th>
              <th>작업장소</th>
              <th>작업시간</th>
              <th>부적합</th>
              <th>제출</th>
            </tr>
          </thead>
          <tbody id="manualWorkTableBody">
            <!-- 수동 입력 행들이 여기에 추가됩니다 -->
          </tbody>
        </table>
      </div>
    </div>
  `;

  // 날짜별로 테이블 생성 (접기/펼치기 가능)
  sortedDates.forEach((dateStr, dateIndex) => {
    const dateData = byDate[dateStr];
    const sessions = Object.values(dateData.sessions);
    const totalWorkers = sessions.reduce((sum, s) => sum + s.items.length, 0);

    // 해당 날짜의 모든 신고 조회
    const relatedIssues = getRelatedIssues(dateStr);
    const nonconformityCount = relatedIssues.filter(i => i.category_type === 'nonconformity').length;
    const safetyCount = relatedIssues.filter(i => i.category_type === 'safety').length;
    const hasIssues = relatedIssues.length > 0;

    // 요일 계산
    const dayNames = ['일', '월', '화', '수', '목', '금', '토'];
    const dayOfWeek = dayNames[new Date(dateStr).getDay()];

    // 오늘 날짜인지 확인
    const today = formatDateForApi(new Date());
    const isToday = dateStr === today;

    // 날짜 그룹 시작 (기본적으로 오늘만 펼침)
    const isExpanded = isToday || dateIndex === 0;

    html += `
      <div class="date-group ${isExpanded ? 'expanded' : 'collapsed'}" data-date="${dateStr}">
        <div class="date-group-header ${hasIssues ? 'has-issues' : ''}" onclick="toggleDateGroup('${dateStr}')">
          <div class="date-header-left">
            <span class="date-toggle-icon">${isExpanded ? '▼' : '▶'}</span>
            <span class="date-title">${formatDate(dateData.date)} (${dayOfWeek})</span>
            ${isToday ? '<span class="today-badge">오늘</span>' : ''}
          </div>
          <div class="date-header-center">
            <span class="date-stat">세션 ${sessions.length}개</span>
            <span class="date-stat">작업자 ${totalWorkers}명</span>
          </div>
          <div class="date-header-right">
            ${hasIssues ? `
              <div class="date-issue-summary">
                ${nonconformityCount > 0 ? `<span class="issue-badge nonconformity">부적합 ${nonconformityCount}</span>` : ''}
                ${safetyCount > 0 ? `<span class="issue-badge safety">안전 ${safetyCount}</span>` : ''}
              </div>
            ` : '<span class="no-issues">신고 없음</span>'}
          </div>
        </div>

        <div class="date-group-content" style="display: ${isExpanded ? 'block' : 'none'};">
    `;

    // 신고 리마인더 HTML 생성 (날짜 그룹 내부)
    if (hasIssues) {
      html += `
        <div class="issue-reminder-section">
          <div class="issue-reminder-header">
            <span class="issue-reminder-icon"></span>
            <span class="issue-reminder-title">당일 신고된 문제</span>
            <span class="issue-reminder-count">${relatedIssues.length}건</span>
          </div>
          <div class="issue-reminder-list">
            ${relatedIssues.slice(0, 5).map(issue => {
              // 아이템명과 추가설명 조합
              let itemText = issue.issue_item_name || '';
              if (issue.additional_description) {
                itemText = itemText ? `${itemText} - ${issue.additional_description}` : issue.additional_description;
              }
              return `
              <div class="issue-reminder-item ${issue.category_type === 'safety' ? 'safety' : 'nonconformity'}">
                <span class="issue-type-badge">${issue.category_type === 'safety' ? '안전' : '부적합'}</span>
                <span class="issue-category">${issue.issue_category_name || ''}</span>
                <span class="issue-item">${itemText || '-'}</span>
                <span class="issue-location">${issue.workplace_name || issue.custom_location || ''}</span>
                <span class="issue-status status-${issue.status}">${getStatusLabel(issue.status)}</span>
              </div>
            `}).join('')}
            ${relatedIssues.length > 5 ? `<div class="issue-reminder-more">외 ${relatedIssues.length - 5}건 더 있음</div>` : ''}
          </div>
          <div class="issue-reminder-hint">
             위 문제로 인해 작업이 지연되었다면, 아래에서 부적합 시간을 추가해주세요.
          </div>
        </div>
      `;
    }

    // 해당 날짜의 각 세션별로 테이블 생성
    sessions.forEach(group => {
      const key = `${group.session_id}_${dateStr}`;

      html += `
        <div class="tbm-session-group" data-session-key="${key}">
          <div class="tbm-session-header">
            <span class="tbm-session-badge">TBM 세션</span>
            <span class="tbm-session-creator">작성자: ${group.created_by_name}</span>
            <span class="tbm-session-count">${group.items.length}명</span>
          </div>
          <div class="tbm-table-container">
            <table class="tbm-work-table">
              <thead>
                <tr>
                  <th>작업자</th>
                  <th>프로젝트</th>
                  <th>공정</th>
                  <th>작업</th>
                  <th>작업장소</th>
                  <th>작업시간</th>
                  <th>부적합</th>
                  <th>제출</th>
                </tr>
              </thead>
              <tbody>
                ${group.items.map(tbm => {
                  const index = tbm.originalIndex;
                  // 이 작업자의 작업장소와 관련된 이슈가 있는지 확인 (부적합 버튼 강조용)
                  const hasRelatedIssue = relatedIssues.some(issue => {
                    if (issue.category_type !== 'nonconformity') return false;
                    // 작업장소 매칭
                    if (tbm.workplace_id && issue.workplace_id) {
                      return tbm.workplace_id === issue.workplace_id;
                    }
                    if (tbm.workplace_name && (issue.workplace_name || issue.custom_location)) {
                      const issueLocation = issue.workplace_name || issue.custom_location || '';
                      return issueLocation.includes(tbm.workplace_name) || tbm.workplace_name.includes(issueLocation);
                    }
                    return false;
                  });
                  return `
                    <tr data-index="${index}" data-type="tbm" data-session-key="${key}">
                      <td>
                        <div class="worker-cell">
                          <strong>${tbm.worker_name || '작업자'}</strong>
                          <div class="worker-job-type">${tbm.job_type || '-'}</div>
                        </div>
                      </td>
                      <td data-label="프로젝트">${tbm.project_name || '-'}</td>
                      <td data-label="공정">${tbm.work_type_name || '-'}</td>
                      <td data-label="작업">${tbm.task_name || '-'}</td>
                      <td data-label="작업장소">
                        <div class="workplace-cell">
                          <div>${tbm.category_name || ''}</div>
                          <div>${tbm.workplace_name || '-'}</div>
                        </div>
                      </td>
                      <td>
                        ${(() => {
                          // TBM 마감 시 확정된 근무시간 자동 계산
                          let autoHours = '';
                          if (tbm.attendance_type === 'overtime') {
                            autoHours = ((tbm.work_hours || 8) + (tbm.attendance_hours || 0)).toString();
                          } else if (tbm.attendance_type === 'early') {
                            autoHours = (tbm.attendance_hours || tbm.work_hours || 8).toString();
                          } else if (tbm.attendance_type === 'regular') {
                            autoHours = (tbm.work_hours || 8).toString();
                          } else if (tbm.work_hours) {
                            autoHours = tbm.work_hours.toString();
                          }
                          const hasAuto = autoHours !== '';
                          return `
                            <input type="hidden" id="totalHours_${index}" value="${autoHours}" required>
                            <div class="time-input-trigger ${hasAuto ? '' : 'placeholder'}"
                                 id="totalHoursDisplay_${index}"
                                 onclick="openTimePicker(${index}, 'total')"
                                 style="${hasAuto ? 'color:#059669;font-weight:600;' : ''}">
                              ${hasAuto ? autoHours + 'h' : '시간 선택'}
                            </div>
                          `;
                        })()}
                      </td>
                      <td>
                        <input type="hidden" id="errorHours_${index}" value="0">
                        <input type="hidden" id="errorType_${index}" value="">
                        <button type="button"
                                class="btn-defect-toggle ${hasRelatedIssue ? 'has-related-issue' : ''}"
                                id="defectToggle_${index}"
                                onclick="toggleDefectArea(${index})">
                          <span id="defectSummary_${index}">없음</span>
                        </button>
                      </td>
                      <td>
                        <button type="button"
                                class="btn-submit-compact"
                                onclick="submitTbmWorkReport(${index})">
                          제출
                        </button>
                      </td>
                    </tr>
                    <tr class="defect-row" id="defectRow_${index}" style="display: none;">
                      <td colspan="8" style="padding: 0.75rem; background: #fef3c7;">
                        <div class="defect-inline-area" id="defectArea_${index}">
                          <div class="defect-list" id="defectList_${index}">
                            <!-- 부적합 원인 목록 (renderInlineDefectList에서 렌더링) -->
                          </div>
                        </div>
                      </td>
                    </tr>
                  `;
                }).join('')}
              </tbody>
            </table>
          </div>
          <div class="batch-submit-container">
            <button type="button"
                    class="btn-batch-submit"
                    onclick="batchSubmitTbmSession('${key}')">
               이 세션 일괄제출 (${group.items.length}건)
            </button>
          </div>
        </div>
      `;
    });

    // 날짜 그룹 닫기
    html += `
        </div>
      </div>
    `;
  });

  container.innerHTML = html;
}

/**
 * 날짜 그룹 접기/펼치기 토글
 */
window.toggleDateGroup = function(dateStr) {
  const group = document.querySelector(`.date-group[data-date="${dateStr}"]`);
  if (!group) return;

  const content = group.querySelector('.date-group-content');
  const icon = group.querySelector('.date-toggle-icon');
  const isExpanded = group.classList.contains('expanded');

  if (isExpanded) {
    group.classList.remove('expanded');
    group.classList.add('collapsed');
    content.style.display = 'none';
    icon.textContent = '▶';
  } else {
    group.classList.remove('collapsed');
    group.classList.add('expanded');
    content.style.display = 'block';
    icon.textContent = '▼';
  }
};

/**
 * 부적합 시간 입력 처리
 */
window.calculateRegularHours = function(index) {
  const errorInput = document.getElementById(`errorHours_${index}`);
  const errorTypeSelect = document.getElementById(`errorType_${index}`);
  const errorTypeNone = document.getElementById(`errorTypeNone_${index}`);

  const errorHours = parseFloat(errorInput.value) || 0;

  // 부적합 시간이 있으면 원인 선택 표시
  if (errorHours > 0) {
    errorTypeSelect.style.display = 'inline-block';
    if (errorTypeNone) errorTypeNone.style.display = 'none';
  } else {
    errorTypeSelect.style.display = 'none';
    if (errorTypeNone) errorTypeNone.style.display = 'inline';
  }
};

/**
 * TBM 작업보고서 제출
 */
window.submitTbmWorkReport = async function(index) {
  // busy guard - 중복 제출 방지
  const submitBtn = document.querySelector(`tr[data-index="${index}"][data-type="tbm"] .btn-submit-compact`);
  if (submitBtn && submitBtn.classList.contains('is-loading')) return;

  const tbm = incompleteTbms[index];

  const totalHours = parseFloat(document.getElementById(`totalHours_${index}`).value);
  const defects = tempDefects[index] || [];

  // 총 부적합 시간 계산
  const errorHours = defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0);
  // item_id를 error_type_id로 사용 (issue_report_items.item_id)
  const errorTypeId = defects.length > 0 ? (defects[0].error_type_id || defects[0].item_id || null) : null;

  // 필수 필드 검증
  if (!totalHours || totalHours <= 0) {
    showMessage('작업시간을 입력해주세요.', 'error');
    return;
  }

  if (errorHours > totalHours) {
    showMessage('부적합 처리 시간은 총 작업시간을 초과할 수 없습니다.', 'error');
    return;
  }

  // 로딩 상태 시작
  if (submitBtn) {
    submitBtn.classList.add('is-loading');
    submitBtn.disabled = true;
    submitBtn.textContent = '제출 중';
  }

  // 부적합 원인 유효성 검사 (issue_report_id 또는 category_id 또는 error_type_id 필요)
  console.log(' 부적합 검증 시작:', defects.map(d => ({
    defect_hours: d.defect_hours,
    category_id: d.category_id,
    item_id: d.item_id,
    error_type_id: d.error_type_id,
    issue_report_id: d.issue_report_id,
    _saved: d._saved
  })));

  const invalidDefects = defects.filter(d => d.defect_hours > 0 && !d.error_type_id && !d.issue_report_id && !d.category_id && !d.item_id);
  if (invalidDefects.length > 0) {
    console.error(' 유효하지 않은 부적합:', invalidDefects);
    showMessage('부적합 시간이 있는 항목은 원인을 선택해주세요.', 'error');
    return;
  }

  // 날짜를 YYYY-MM-DD 형식으로 변환
  const reportDate = tbm.session_date instanceof Date
    ? tbm.session_date.toISOString().split('T')[0]
    : (typeof tbm.session_date === 'string' && tbm.session_date.includes('T')
      ? tbm.session_date.split('T')[0]
      : tbm.session_date);

  const reportData = {
    tbm_assignment_id: tbm.assignment_id,
    tbm_session_id: tbm.session_id,
    user_id: tbm.user_id,
    project_id: tbm.project_id,
    work_type_id: tbm.task_id, // task_id를 work_type_id 컬럼에 저장 (직접 작업보고서와 일관성 유지)
    report_date: reportDate,
    start_time: null,
    end_time: null,
    total_hours: totalHours,
    error_hours: errorHours,
    error_type_id: errorTypeId,
    work_status_id: errorHours > 0 ? 2 : 1
  };


  try {
    const response = await window.apiCall('/daily-work-reports/from-tbm', 'POST', reportData);

    if (!response.success) {
      throw new Error(response.message || '작업보고서 제출 실패');
    }

    // 부적합 원인이 있으면 저장 (이슈 기반 또는 레거시)
    if (defects.length > 0 && response.data?.report_id) {
      const validDefects = defects.filter(d => (d.issue_report_id || d.category_id || d.item_id || d.error_type_id) && d.defect_hours > 0);
      console.log(' 부적합 원인 필터링:', {
        전체: defects.length,
        유효: validDefects.length,
        validDefects: validDefects.map(d => ({
          category_id: d.category_id,
          item_id: d.item_id,
          defect_hours: d.defect_hours,
          _saved: d._saved
        }))
      });

      if (validDefects.length > 0) {
        // 내부 플래그 제거 (백엔드 전송용)
        const defectsToSend = validDefects.map(d => ({
          issue_report_id: d.issue_report_id || null,
          category_id: d.category_id || null,
          item_id: d.item_id || null,
          error_type_id: d.error_type_id || null,
          defect_hours: d.defect_hours,
          note: d.note || ''
        }));


        const defectResponse = await window.apiCall(`/daily-work-reports/${response.data.report_id}/defects`, 'PUT', {
          defects: defectsToSend
        });

        if (!defectResponse.success) {
          console.error(' 부적합 저장 실패:', defectResponse);
          showMessage('작업보고서는 저장되었으나 부적합 원인 저장에 실패했습니다.', 'warning');
        } else {
        }
      } else {
      }
    }

    showSaveResultModal(
      'success',
      '작업보고서 제출 완료',
      `${tbm.worker_name}의 작업보고서가 성공적으로 제출되었습니다.`,
      response.data.tbm_completed ?
        '모든 팀원의 작업보고서가 제출되어 TBM이 완료되었습니다.' :
        response.data.completion_status
    );

    // 임시 부적합 데이터 삭제
    delete tempDefects[index];

    // 목록 새로고침
    await loadIncompleteTbms();
  } catch (error) {
    console.error('TBM 작업보고서 제출 오류:', error);
    showSaveResultModal('error', '제출 실패', error.message);
  } finally {
    // 로딩 상태 해제
    if (submitBtn) {
      submitBtn.classList.remove('is-loading');
      submitBtn.disabled = false;
      submitBtn.textContent = '제출';
    }
  }
};

/**
 * TBM 세션 일괄제출
 */
window.batchSubmitTbmSession = async function(sessionKey) {
  // busy guard - 일괄제출 버튼
  const batchBtn = document.querySelector(`[data-session-key="${sessionKey}"] ~ .batch-submit-container .btn-batch-submit, .tbm-session-group[data-session-key="${sessionKey}"] .btn-batch-submit`);
  if (batchBtn && batchBtn.classList.contains('is-loading')) return;

  // 해당 세션의 모든 항목 가져오기
  const sessionRows = document.querySelectorAll(`tr[data-session-key="${sessionKey}"]`);

  if (sessionRows.length === 0) {
    showMessage('제출할 항목이 없습니다.', 'error');
    return;
  }

  // 1단계: 모든 항목 검증
  const validationErrors = [];
  const itemsToSubmit = [];

  sessionRows.forEach((row, rowIndex) => {
    const index = parseInt(row.getAttribute('data-index'));
    const tbm = incompleteTbms[index];

    const totalHours = parseFloat(document.getElementById(`totalHours_${index}`)?.value);
    const errorHours = parseFloat(document.getElementById(`errorHours_${index}`)?.value) || 0;
    const errorTypeId = document.getElementById(`errorType_${index}`)?.value;

    // 검증
    if (!totalHours || totalHours <= 0) {
      validationErrors.push(`${tbm.worker_name}: 작업시간 미입력`);
      return;
    }

    if (errorHours > totalHours) {
      validationErrors.push(`${tbm.worker_name}: 부적합 시간이 총 작업시간 초과`);
      return;
    }

    if (errorHours > 0 && !errorTypeId) {
      validationErrors.push(`${tbm.worker_name}: 부적합 원인 미선택`);
      return;
    }

    // 검증 통과한 항목 저장
    const reportDate = tbm.session_date instanceof Date
      ? tbm.session_date.toISOString().split('T')[0]
      : (typeof tbm.session_date === 'string' && tbm.session_date.includes('T')
        ? tbm.session_date.split('T')[0]
        : tbm.session_date);

    itemsToSubmit.push({
      index,
      tbm,
      data: {
        tbm_assignment_id: tbm.assignment_id,
        tbm_session_id: tbm.session_id,
        user_id: tbm.user_id,
        project_id: tbm.project_id,
        work_type_id: tbm.task_id, // task_id를 work_type_id 컬럼에 저장 (일관성 유지)
        report_date: reportDate,
        start_time: null,
        end_time: null,
        total_hours: totalHours,
        error_hours: errorHours,
        error_type_id: errorTypeId || null,
        work_status_id: errorHours > 0 ? 2 : 1
      }
    });
  });

  // 검증 실패가 하나라도 있으면 전체 중단
  if (validationErrors.length > 0) {
    showSaveResultModal(
      'error',
      '일괄제출 검증 실패',
      '모든 항목이 유효해야 제출할 수 있습니다.',
      validationErrors
    );
    return;
  }

  // 2단계: 모든 항목 제출
  const submitBtn = batchBtn || event.target;
  submitBtn.classList.add('is-loading');
  submitBtn.disabled = true;
  submitBtn.textContent = '제출 중...';

  const results = {
    success: [],
    failed: []
  };

  try {
    for (const item of itemsToSubmit) {
      try {
        const response = await window.apiCall('/daily-work-reports/from-tbm', 'POST', item.data);

        if (response.success) {
          results.success.push(item.tbm.worker_name);
        } else {
          results.failed.push(`${item.tbm.worker_name}: ${response.message}`);
        }
      } catch (error) {
        results.failed.push(`${item.tbm.worker_name}: ${error.message}`);
      }
    }

    // 결과 표시
    const totalCount = itemsToSubmit.length;
    const successCount = results.success.length;
    const failedCount = results.failed.length;

    if (failedCount === 0) {
      // 모두 성공
      showSaveResultModal(
        'success',
        '일괄제출 완료',
        `${totalCount}건의 작업보고서가 모두 성공적으로 제출되었습니다.`,
        results.success.map(name => ` ${name}`)
      );
    } else if (successCount === 0) {
      // 모두 실패
      showSaveResultModal(
        'error',
        '일괄제출 실패',
        `${totalCount}건의 작업보고서가 모두 실패했습니다.`,
        results.failed.map(msg => ` ${msg}`)
      );
    } else {
      // 일부 성공, 일부 실패
      const details = [
        ...results.success.map(name => ` ${name} - 성공`),
        ...results.failed.map(msg => ` ${msg}`)
      ];
      showSaveResultModal(
        'warning',
        '일괄제출 부분 완료',
        `성공: ${successCount}건 / 실패: ${failedCount}건`,
        details
      );
    }

    // 목록 새로고침
    await loadIncompleteTbms();
  } catch (error) {
    console.error('일괄제출 오류:', error);
    showSaveResultModal('error', '일괄제출 오류', error.message);
  } finally {
    submitBtn.classList.remove('is-loading');
    submitBtn.disabled = false;
    submitBtn.textContent = ` 이 세션 일괄제출 (${sessionRows.length}건)`;
  }
};

/**
 * 수동 작업 추가
 */
window.addManualWorkRow = function() {
  const tbody = document.getElementById('manualWorkTableBody');
  if (!tbody) {
    showMessage('수동 입력 테이블을 찾을 수 없습니다.', 'error');
    return;
  }

  const manualIndex = `manual_${workEntryCounter++}`;

  const newRow = document.createElement('tr');
  newRow.setAttribute('data-index', manualIndex);
  newRow.setAttribute('data-type', 'manual');

  newRow.innerHTML = `
    <td>
      <select class="form-input-compact" id="worker_${manualIndex}" style="width: 120px;" required>
        <option value="">작업자 선택</option>
        ${workers.map(w => `<option value="${escapeHtml(String(w.user_id))}">${escapeHtml(w.worker_name)} (${escapeHtml(w.job_type || '-')})</option>`).join('')}
      </select>
    </td>
    <td>
      <input type="date" class="form-input-compact" id="date_${manualIndex}" value="${escapeHtml(getKoreaToday())}" required style="width: 130px;">
    </td>
    <td>
      <select class="form-input-compact" id="project_${manualIndex}" style="width: 120px;" required>
        <option value="">프로젝트 선택</option>
        ${projects.map(p => `<option value="${escapeHtml(String(p.project_id))}">${escapeHtml(p.project_name)}</option>`).join('')}
      </select>
    </td>
    <td>
      <select class="form-input-compact" id="workType_${manualIndex}" style="width: 120px;" required onchange="loadTasksForWorkType('${manualIndex}')">
        <option value="">공정 선택</option>
        ${workTypes.map(wt => `<option value="${escapeHtml(String(wt.id))}">${escapeHtml(wt.name)}</option>`).join('')}
      </select>
    </td>
    <td>
      <select class="form-input-compact" id="task_${manualIndex}" style="width: 120px;" required disabled>
        <option value="">공정을 먼저 선택하세요</option>
      </select>
    </td>
    <td style="min-width: 180px;">
      <input type="hidden" id="workplaceCategory_${manualIndex}">
      <input type="hidden" id="workplace_${manualIndex}">
      <div id="workplaceDisplay_${manualIndex}" class="workplace-select-box" style="display: flex; flex-direction: column; gap: 0.25rem; padding: 0.5rem; background: #f9fafb; border: 2px solid #e5e7eb; border-radius: 6px; min-height: 60px; cursor: pointer;" onclick="openWorkplaceMapForManual('${manualIndex}')">
        <div style="display: flex; align-items: center; gap: 0.5rem; font-size: 0.75rem; color: #6b7280; font-weight: 500;">
          <span></span>
          <span>작업장소</span>
        </div>
        <div id="workplaceText_${manualIndex}" style="font-size: 0.8rem; color: #9ca3af; font-style: italic;">
          클릭하여 선택
        </div>
      </div>
    </td>
    <td>
      <input type="hidden" id="totalHours_${manualIndex}" value="" required>
      <div class="time-input-trigger placeholder"
           id="totalHoursDisplay_${manualIndex}"
           onclick="openTimePicker('${manualIndex}', 'total')">
        시간 선택
      </div>
    </td>
    <td>
      <input type="hidden" id="errorHours_${manualIndex}" value="0">
      <input type="hidden" id="errorType_${manualIndex}" value="">
      <button type="button"
              class="btn-defect-toggle"
              id="defectToggle_${manualIndex}"
              onclick="toggleDefectArea('${manualIndex}')">
        <span id="defectSummary_${manualIndex}">없음</span>
      </button>
    </td>
    <td>
      <button type="button" class="btn-submit-compact" onclick="submitManualWorkReport('${manualIndex}')">
        제출
      </button>
      <button type="button" class="btn-delete-compact" onclick="removeManualWorkRow('${manualIndex}')" style="margin-left: 4px;">
        
      </button>
    </td>
  `;

  tbody.appendChild(newRow);

  // 부적합 인라인 영역 행 추가
  const defectRow = document.createElement('tr');
  defectRow.className = 'defect-row';
  defectRow.id = `defectRow_${manualIndex}`;
  defectRow.style.display = 'none';
  defectRow.innerHTML = `
    <td colspan="9" style="padding: 0; background: #fef3c7;">
      <div class="defect-inline-area" id="defectArea_${manualIndex}">
        <div class="defect-list" id="defectList_${manualIndex}">
          <!-- 부적합 원인 목록 -->
        </div>
        <button type="button" class="btn-add-defect-inline" onclick="addInlineDefect('${manualIndex}')">
          + 부적합 추가
        </button>
      </div>
    </td>
  `;
  tbody.appendChild(defectRow);

  showMessage('새 작업 행이 추가되었습니다. 정보를 입력하고 제출하세요.', 'info');
};

/**
 * 수동 작업 행 제거
 */
window.removeManualWorkRow = function(manualIndex) {
  const row = document.querySelector(`tr[data-index="${manualIndex}"]`);
  const defectRow = document.getElementById(`defectRow_${manualIndex}`);
  if (row) {
    row.remove();
  }
  if (defectRow) {
    defectRow.remove();
  }
  // 임시 부적합 데이터도 삭제
  delete tempDefects[manualIndex];
};

/**
 * 공정 선택 시 작업 목록 로드
 */
window.loadTasksForWorkType = async function(manualIndex) {
  const workTypeId = document.getElementById(`workType_${manualIndex}`).value;
  const taskSelect = document.getElementById(`task_${manualIndex}`);

  if (!workTypeId) {
    taskSelect.disabled = true;
    taskSelect.innerHTML = '<option value="">공정을 먼저 선택하세요</option>';
    return;
  }

  try {
    // 해당 공정의 작업 목록 조회
    const response = await window.apiCall(`/tasks?work_type_id=${workTypeId}`);
    const tasks = response.success ? response.data : (Array.isArray(response) ? response : []);

    if (tasks && tasks.length > 0) {
      taskSelect.disabled = false;
      taskSelect.innerHTML = `
        <option value="">작업 선택</option>
        ${tasks.map(task => `<option value="${escapeHtml(String(task.task_id))}">${escapeHtml(task.task_name)}</option>`).join('')}
      `;
    } else {
      taskSelect.disabled = true;
      taskSelect.innerHTML = '<option value="">등록된 작업이 없습니다</option>';
    }
  } catch (error) {
    console.error('작업 목록 로드 오류:', error);
    taskSelect.disabled = true;
    taskSelect.innerHTML = '<option value="">작업 로드 실패</option>';
  }
};

/**
 * 수동 입력 부적합 시간 토글
 */
window.toggleManualErrorType = function(manualIndex) {
  const errorInput = document.getElementById(`errorHours_${manualIndex}`);
  const errorTypeSelect = document.getElementById(`errorType_${manualIndex}`);
  const errorTypeNone = document.getElementById(`errorTypeNone_${manualIndex}`);

  const errorHours = parseFloat(errorInput.value) || 0;

  if (errorHours > 0) {
    errorTypeSelect.style.display = 'inline-block';
    if (errorTypeNone) errorTypeNone.style.display = 'none';
  } else {
    errorTypeSelect.style.display = 'none';
    if (errorTypeNone) errorTypeNone.style.display = 'inline';
  }
};

/**
 * 수동 입력용 작업장소 선택 모달 열기
 */
window.openWorkplaceMapForManual = async function(manualIndex) {
  window.currentManualIndex = manualIndex;

  // 변수 초기화
  selectedWorkplace = null;
  selectedWorkplaceName = null;
  selectedWorkplaceCategory = null;
  selectedWorkplaceCategoryName = null;

  try {
    // 작업장소 카테고리 로드
    const categoriesResponse = await window.apiCall('/workplaces/categories');
    const categories = categoriesResponse.success ? categoriesResponse.data : categoriesResponse;

    // 작업장소 모달 표시
    const modal = document.getElementById('workplaceModal');
    const categoryList = document.getElementById('workplaceCategoryList');

    categoryList.innerHTML = categories.map(cat => {
      const safeId = parseInt(cat.category_id) || 0;
      const safeName = escapeHtml(cat.category_name);
      const safeImage = escapeHtml(cat.layout_image || '');
      return `
      <button type="button" class="btn btn-secondary" style="width: 100%; text-align: left;" onclick='selectWorkplaceCategory(${safeId}, "${safeName.replace(/"/g, '&quot;')}", "${safeImage.replace(/"/g, '&quot;')}")'>
        <span style="margin-right: 0.5rem;"></span>
        ${safeName}
      </button>
    `;
    }).join('') + `
      <button type="button" class="btn btn-secondary" style="width: 100%; text-align: left; margin-top: 0.5rem; background-color: #f0f9ff; border-color: #0ea5e9;" onclick='selectExternalWorkplace()'>
        <span style="margin-right: 0.5rem;"></span>
        외부 (외근/연차/휴무 등)
      </button>
    `;

    // 카테고리 선택 화면 표시
    document.getElementById('categorySelectionArea').style.display = 'block';
    document.getElementById('workplaceSelectionArea').style.display = 'none';

    modal.style.display = 'flex';
  } catch (error) {
    console.error('작업장소 카테고리 로드 오류:', error);
    showMessage('작업장소 목록을 불러오는 중 오류가 발생했습니다.', 'error');
  }
};

/**
 * 작업장소 카테고리 선택
 */
window.selectWorkplaceCategory = async function(categoryId, categoryName, layoutImage) {
  selectedWorkplaceCategory = categoryId;
  selectedWorkplaceCategoryName = categoryName;

  try {
    // 타이틀 업데이트
    document.getElementById('selectedCategoryTitle').textContent = `${categoryName} - 작업장 선택`;

    // 카테고리 화면 숨기고 작업장 선택 화면 표시
    document.getElementById('categorySelectionArea').style.display = 'none';
    document.getElementById('workplaceSelectionArea').style.display = 'block';

    // 해당 카테고리의 작업장소 로드
    const workplacesResponse = await window.apiCall(`/workplaces?category_id=${categoryId}`);
    const workplaces = workplacesResponse.success ? workplacesResponse.data : workplacesResponse;

    // 지도 또는 리스트 로드
    if (layoutImage && layoutImage !== '') {
      // 지도가 있는 경우 - 지도 영역 표시
      await loadWorkplaceMap(categoryId, layoutImage, workplaces);
      document.getElementById('layoutMapArea').style.display = 'block';
    } else {
      // 지도가 없는 경우 - 리스트만 표시
      document.getElementById('layoutMapArea').style.display = 'none';
    }

    // 리스트 항상 표시
    const workplaceListArea = document.getElementById('workplaceListArea');
    workplaceListArea.innerHTML = workplaces.map(wp => {
      const safeId = parseInt(wp.workplace_id) || 0;
      const safeName = escapeHtml(wp.workplace_name);
      return `
      <button type="button" id="workplace-${safeId}" class="btn btn-secondary" style="width: 100%; text-align: left;" onclick='selectWorkplaceFromList(${safeId}, "${safeName.replace(/"/g, '&quot;')}")'>
        <span style="margin-right: 0.5rem;"></span>
        ${safeName}
      </button>
    `;
    }).join('');

  } catch (error) {
    console.error('작업장소 로드 오류:', error);
    showMessage('작업장소를 불러오는 중 오류가 발생했습니다.', 'error');
  }
};

/**
 * 작업장소 지도 로드
 */
async function loadWorkplaceMap(categoryId, layoutImagePath, workplaces) {
  try {
    mapCanvas = document.getElementById('workplaceMapCanvas');
    if (!mapCanvas) return;

    mapCtx = mapCanvas.getContext('2d');

    // 이미지 URL 생성
    const baseUrl = window.API_BASE_URL || 'http://localhost:20005';
    const apiBaseUrl = baseUrl.replace('/api', ''); // /api 제거
    const fullImageUrl = layoutImagePath.startsWith('http')
      ? layoutImagePath
      : `${apiBaseUrl}${layoutImagePath}`;


    // 지도 영역 데이터 로드
    const regionsResponse = await window.apiCall(`/workplaces/categories/${categoryId}/map-regions`);
    if (regionsResponse && regionsResponse.success) {
      mapRegions = regionsResponse.data || [];
    } else {
      mapRegions = [];
    }

    // 이미지 로드
    mapImage = new Image();
    mapImage.crossOrigin = 'anonymous';

    mapImage.onload = function() {
      // 캔버스 크기 설정 (최대 너비 800px)
      const maxWidth = 800;
      const scale = mapImage.width > maxWidth ? maxWidth / mapImage.width : 1;

      mapCanvas.width = mapImage.width * scale;
      mapCanvas.height = mapImage.height * scale;

      // 이미지와 영역 그리기
      drawWorkplaceMap();

      // 클릭 이벤트 리스너 추가
      mapCanvas.onclick = handleMapClick;

    };

    mapImage.onerror = function() {
      console.error(' 지도 이미지 로드 실패');
      document.getElementById('layoutMapArea').style.display = 'none';
      showMessage('지도를 불러올 수 없어 리스트로 표시합니다.', 'warning');
    };

    mapImage.src = fullImageUrl;

  } catch (error) {
    console.error(' 작업장 지도 로드 오류:', error);
    document.getElementById('layoutMapArea').style.display = 'none';
  }
}

/**
 * 지도 그리기
 */
function drawWorkplaceMap() {
  if (!mapCanvas || !mapCtx || !mapImage) return;

  // 이미지 그리기
  mapCtx.drawImage(mapImage, 0, 0, mapCanvas.width, mapCanvas.height);

  // 각 영역 그리기
  mapRegions.forEach((region) => {
    // 퍼센트를 픽셀로 변환
    const x1 = (region.x_start / 100) * mapCanvas.width;
    const y1 = (region.y_start / 100) * mapCanvas.height;
    const x2 = (region.x_end / 100) * mapCanvas.width;
    const y2 = (region.y_end / 100) * mapCanvas.height;

    const width = x2 - x1;
    const height = y2 - y1;

    // 선택된 영역인지 확인
    const isSelected = region.workplace_id === selectedWorkplace;

    // 영역 테두리
    mapCtx.strokeStyle = isSelected ? '#3b82f6' : '#10b981';
    mapCtx.lineWidth = isSelected ? 4 : 2;
    mapCtx.strokeRect(x1, y1, width, height);

    // 영역 배경 (반투명)
    mapCtx.fillStyle = isSelected ? 'rgba(59, 130, 246, 0.25)' : 'rgba(16, 185, 129, 0.15)';
    mapCtx.fillRect(x1, y1, width, height);

    // 작업장 이름 표시
    if (region.workplace_name) {
      mapCtx.font = 'bold 14px sans-serif';

      // 텍스트 배경
      const textMetrics = mapCtx.measureText(region.workplace_name);
      const textPadding = 6;
      mapCtx.fillStyle = isSelected ? 'rgba(59, 130, 246, 0.95)' : 'rgba(16, 185, 129, 0.95)';
      mapCtx.fillRect(x1 + 5, y1 + 5, textMetrics.width + textPadding * 2, 24);

      // 텍스트
      mapCtx.fillStyle = '#ffffff';
      mapCtx.fillText(region.workplace_name, x1 + 5 + textPadding, y1 + 22);
    }
  });
}

/**
 * 지도 클릭 이벤트 처리
 */
function handleMapClick(event) {
  if (!mapCanvas || mapRegions.length === 0) return;

  const rect = mapCanvas.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;

  // 클릭한 위치에 있는 영역 찾기
  for (let i = mapRegions.length - 1; i >= 0; i--) {
    const region = mapRegions[i];
    const x1 = (region.x_start / 100) * mapCanvas.width;
    const y1 = (region.y_start / 100) * mapCanvas.height;
    const x2 = (region.x_end / 100) * mapCanvas.width;
    const y2 = (region.y_end / 100) * mapCanvas.height;

    if (x >= x1 && x <= x2 && y >= y1 && y <= y2) {
      // 영역 클릭됨
      selectWorkplaceFromList(region.workplace_id, region.workplace_name);
      return;
    }
  }
}

/**
 * 리스트에서 작업장소 선택
 */
window.selectWorkplaceFromList = function(workplaceId, workplaceName) {
  selectedWorkplace = workplaceId;
  selectedWorkplaceName = workplaceName;

  // 지도 다시 그리기 (선택 효과 표시)
  if (mapCanvas && mapCtx && mapImage) {
    drawWorkplaceMap();
  }

  // 리스트 버튼 업데이트
  document.querySelectorAll('[id^="workplace-"]').forEach(btn => {
    if (btn.id === `workplace-${workplaceId}`) {
      btn.classList.remove('btn-secondary');
      btn.classList.add('btn-primary');
    } else {
      btn.classList.remove('btn-primary');
      btn.classList.add('btn-secondary');
    }
  });

  // 선택 완료 버튼 활성화
  document.getElementById('confirmWorkplaceBtn').disabled = false;
};

/**
 * 작업장소 선택 완료
 */
window.confirmWorkplaceSelection = function() {
  const manualIndex = window.currentManualIndex;

  if (!selectedWorkplace || !selectedWorkplaceCategory) {
    showMessage('작업장소를 선택해주세요.', 'error');
    return;
  }

  document.getElementById(`workplaceCategory_${manualIndex}`).value = selectedWorkplaceCategory;
  document.getElementById(`workplace_${manualIndex}`).value = selectedWorkplace;

  const displayDiv = document.getElementById(`workplaceDisplay_${manualIndex}`);
  if (displayDiv) {
    displayDiv.innerHTML = `
      <div style="display: flex; align-items: center; gap: 0.5rem; font-size: 0.75rem; color: #059669; font-weight: 600;">
        <span></span>
        <span>작업장소 선택됨</span>
      </div>
      <div style="font-size: 0.8rem; color: #111827; font-weight: 500;">
        <div style="color: #6b7280; font-size: 0.7rem; margin-bottom: 2px;"> ${escapeHtml(selectedWorkplaceCategoryName)}</div>
        <div> ${escapeHtml(selectedWorkplaceName)}</div>
      </div>
    `;
    displayDiv.style.background = '#ecfdf5';
    displayDiv.style.borderColor = '#10b981';
  }

  // 모달 닫기
  closeWorkplaceModal();
  showMessage('작업장소가 선택되었습니다.', 'success');
};

/**
 * 작업장소 모달 닫기
 */
window.closeWorkplaceModal = function() {
  document.getElementById('workplaceModal').style.display = 'none';

  // 초기화
  selectedWorkplace = null;
  selectedWorkplaceName = null;
  mapCanvas = null;
  mapCtx = null;
  mapImage = null;
  mapRegions = [];
};

/**
 * 외부 작업장소 선택 (외근/연차/휴무 등)
 */
window.selectExternalWorkplace = function() {
  const manualIndex = window.currentManualIndex;

  // 외부 작업장소 ID는 0 또는 특별한 값으로 설정 (DB에 저장시 처리 필요)
  const externalCategoryId = 0;
  const externalCategoryName = '외부';
  const externalWorkplaceId = 0;
  const externalWorkplaceName = '외부 (외근/연차/휴무)';

  // hidden input에 값 설정
  document.getElementById(`workplaceCategory_${manualIndex}`).value = externalCategoryId;
  document.getElementById(`workplace_${manualIndex}`).value = externalWorkplaceId;

  // 선택 결과 표시
  const displayDiv = document.getElementById(`workplaceDisplay_${manualIndex}`);
  if (displayDiv) {
    displayDiv.innerHTML = `
      <div style="display: flex; align-items: center; gap: 0.5rem; font-size: 0.75rem; color: #0284c7; font-weight: 600;">
        <span></span>
        <span>외부 선택됨</span>
      </div>
      <div style="font-size: 0.8rem; color: #111827; font-weight: 500;">
        <div> ${escapeHtml(externalWorkplaceName)}</div>
      </div>
    `;
    displayDiv.style.background = '#f0f9ff';
    displayDiv.style.borderColor = '#0ea5e9';
  }

  // 모달 닫기
  document.getElementById('workplaceModal').style.display = 'none';
  showMessage('외부 작업장소가 선택되었습니다.', 'success');
};

/**
 * 수동 작업보고서 제출
 */
window.submitManualWorkReport = async function(manualIndex) {
  const workerId = document.getElementById(`worker_${manualIndex}`).value;
  const reportDate = document.getElementById(`date_${manualIndex}`).value;
  const projectId = document.getElementById(`project_${manualIndex}`).value;
  const workTypeId = document.getElementById(`workType_${manualIndex}`).value;
  const taskId = document.getElementById(`task_${manualIndex}`).value;
  const workplaceCategoryId = document.getElementById(`workplaceCategory_${manualIndex}`).value;
  const workplaceId = document.getElementById(`workplace_${manualIndex}`).value;
  const totalHours = parseFloat(document.getElementById(`totalHours_${manualIndex}`).value);

  // 부적합 원인 가져오기
  const defects = tempDefects[manualIndex] || [];
  const errorHours = defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0);
  // item_id를 error_type_id로 사용 (issue_report_items.item_id)
  const errorTypeId = defects.length > 0 ? (defects[0].error_type_id || defects[0].item_id || null) : null;

  // 필수 필드 검증
  if (!workerId) {
    showMessage('작업자를 선택해주세요.', 'error');
    return;
  }
  if (!reportDate) {
    showMessage('작업 날짜를 입력해주세요.', 'error');
    return;
  }
  if (!projectId) {
    showMessage('프로젝트를 선택해주세요.', 'error');
    return;
  }
  if (!workTypeId) {
    showMessage('공정을 선택해주세요.', 'error');
    return;
  }
  if (!taskId) {
    showMessage('작업을 선택해주세요.', 'error');
    return;
  }
  if (workplaceId === '' || workplaceId === null || workplaceId === undefined) {
    showMessage('작업장소를 선택해주세요.', 'error');
    return;
  }
  if (!totalHours || totalHours <= 0) {
    showMessage('작업시간을 입력해주세요.', 'error');
    return;
  }

  if (errorHours > totalHours) {
    showMessage('부적합 처리 시간은 총 작업시간을 초과할 수 없습니다.', 'error');
    return;
  }

  // 부적합 원인 유효성 검사 (issue_report_id 또는 error_type_id 필요)
  const invalidDefects = defects.filter(d => d.defect_hours > 0 && !d.error_type_id && !d.issue_report_id && !d.category_id && !d.item_id);
  if (invalidDefects.length > 0) {
    showMessage('부적합 시간이 있는 항목은 원인을 선택해주세요.', 'error');
    return;
  }

  // 서비스 레이어가 기대하는 형식으로 변환
  // 주의: 서비스에서 task_id를 work_type_id 컬럼에 매핑함
  const reportData = {
    report_date: reportDate,
    user_id: parseInt(workerId),
    work_entries: [{
      project_id: parseInt(projectId),
      task_id: parseInt(taskId),  // 서비스에서 work_type_id로 매핑됨
      work_hours: totalHours,
      work_status_id: errorHours > 0 ? 2 : 1,
      error_type_id: errorTypeId ? parseInt(errorTypeId) : null
    }]
  };

  try {
    // 429 오류 재시도 로직 포함
    let response;
    let retries = 3;
    for (let i = 0; i < retries; i++) {
      try {
        response = await window.apiCall('/daily-work-reports', 'POST', reportData);
        break;
      } catch (err) {
        if ((err.message?.includes('429') || err.message?.includes('너무 많은 요청')) && i < retries - 1) {
          const waitTime = (i + 1) * 2000;
          showMessage(`서버가 바쁩니다. ${waitTime/1000}초 후 재시도...`, 'loading');
          await new Promise(r => setTimeout(r, waitTime));
          continue;
        }
        throw err;
      }
    }

    if (!response.success) {
      throw new Error(response.message || '작업보고서 제출 실패');
    }

    // 부적합 원인이 있으면 저장 (이슈 기반 또는 레거시)
    const reportId = response.data?.inserted_ids?.[0] || response.data?.workReport_ids?.[0];
    if (defects.length > 0 && reportId) {
      const validDefects = defects.filter(d => (d.issue_report_id || d.category_id || d.item_id || d.error_type_id) && d.defect_hours > 0);
      if (validDefects.length > 0) {
        await window.apiCall(`/daily-work-reports/${reportId}/defects`, 'PUT', {
          defects: validDefects
        });
      }
    }

    // 행 제거 (부적합 임시 데이터도 함께 삭제됨)
    removeManualWorkRow(manualIndex);

    showMessage('작업보고서가 제출되었습니다.', 'success');

    // 남은 행이 없으면 완료 메시지
    const remainingRows = document.querySelectorAll('#manualWorkTableBody tr[data-index]');
    if (remainingRows.length === 0) {
      showSaveResultModal(
        'success',
        '작업보고서 제출 완료',
        '모든 작업보고서가 성공적으로 제출되었습니다.'
      );
    }
  } catch (error) {
    console.error('수동 작업보고서 제출 오류:', error);
    showMessage('제출 실패: ' + error.message, 'error');
  }
};

/**
 * 딜레이 함수
 */
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

/**
 * API 호출 (429 재시도 포함)
 */
async function apiCallWithRetry(url, method, data, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await window.apiCall(url, method, data);
      return response;
    } catch (error) {
      // 429 Rate Limit 오류인 경우 재시도
      if (error.message && error.message.includes('429') || error.message.includes('너무 많은 요청')) {
        if (attempt < maxRetries) {
          const waitTime = attempt * 2000; // 2초, 4초, 6초 대기
          console.log(`Rate limit 도달. ${waitTime/1000}초 후 재시도... (${attempt}/${maxRetries})`);
          await delay(waitTime);
          continue;
        }
      }
      throw error;
    }
  }
}

/**
 * 수동 작업보고서 일괄 제출
 */
window.submitAllManualWorkReports = async function() {
  const rows = document.querySelectorAll('#manualWorkTableBody tr[data-index]');

  if (rows.length === 0) {
    showMessage('제출할 작업보고서가 없습니다.', 'error');
    return;
  }

  // 확인 다이얼로그
  if (!confirm(`${rows.length}개의 작업보고서를 일괄 제출하시겠습니까?`)) {
    return;
  }

  let successCount = 0;
  let failCount = 0;
  const errors = [];
  let currentIndex = 0;

  showMessage(`작업보고서 제출 중... (0/${rows.length})`, 'loading');

  // 각 행을 순차적으로 제출 (딜레이 포함)
  for (const row of rows) {
    currentIndex++;
    const manualIndex = row.dataset.index;

    // Rate Limit 방지를 위한 딜레이 (1초)
    if (currentIndex > 1) {
      await delay(1000);
    }

    showMessage(`작업보고서 제출 중... (${currentIndex}/${rows.length})`, 'loading');

    try {
      const workerId = document.getElementById(`worker_${manualIndex}`).value;
      const reportDate = document.getElementById(`date_${manualIndex}`).value;
      const projectId = document.getElementById(`project_${manualIndex}`).value;
      const workTypeId = document.getElementById(`workType_${manualIndex}`).value;
      const taskId = document.getElementById(`task_${manualIndex}`).value;
      const workplaceCategoryId = document.getElementById(`workplaceCategory_${manualIndex}`).value;
      const workplaceId = document.getElementById(`workplace_${manualIndex}`).value;
      const totalHours = parseFloat(document.getElementById(`totalHours_${manualIndex}`).value);

      // 부적합 원인 가져오기
      const defects = tempDefects[manualIndex] || [];
      const errorHours = defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0);
      // item_id를 error_type_id로 사용 (issue_report_items.item_id)
  const errorTypeId = defects.length > 0 ? (defects[0].error_type_id || defects[0].item_id || null) : null;

      // 필수 필드 검증
      if (!workerId || !reportDate || !projectId || !workTypeId || !taskId || !totalHours || totalHours <= 0) {
        errors.push(`행 ${manualIndex}: 필수 항목 누락`);
        failCount++;
        continue;
      }

      if (workplaceId === '' || workplaceId === null || workplaceId === undefined) {
        errors.push(`행 ${manualIndex}: 작업장소 미선택`);
        failCount++;
        continue;
      }

      // 서비스 레이어가 기대하는 형식으로 변환
      const reportData = {
        report_date: reportDate,
        user_id: parseInt(workerId),
        work_entries: [{
          project_id: parseInt(projectId),
          task_id: parseInt(taskId),
          work_hours: totalHours,
          work_status_id: errorHours > 0 ? 2 : 1,
          error_type_id: errorTypeId ? parseInt(errorTypeId) : null
        }]
      };

      const response = await apiCallWithRetry('/daily-work-reports', 'POST', reportData);

      if (!response.success) {
        throw new Error(response.message || '작업보고서 제출 실패');
      }

      // 부적합 원인이 있으면 저장
      const reportId = response.data?.inserted_ids?.[0] || response.data?.workReport_ids?.[0];
      if (defects.length > 0 && reportId) {
        const validDefects = defects.filter(d => (d.issue_report_id || d.category_id || d.item_id || d.error_type_id) && d.defect_hours > 0);
        if (validDefects.length > 0) {
          await apiCallWithRetry(`/daily-work-reports/${reportId}/defects`, 'PUT', {
            defects: validDefects
          });
        }
      }

      // 성공 - 행 제거
      removeManualWorkRow(manualIndex);
      successCount++;

    } catch (error) {
      console.error(`행 ${manualIndex} 제출 오류:`, error);
      errors.push(`행 ${manualIndex}: ${error.message}`);
      failCount++;
    }
  }

  // 로딩 메시지 숨기기
  hideMessage();

  // 결과 표시
  let resultMessage = `성공: ${successCount}건`;
  if (failCount > 0) {
    resultMessage += `, 실패: ${failCount}건`;
  }

  if (failCount > 0 && errors.length > 0) {
    showSaveResultModal(
      'warning',
      '일괄 제출 완료 (일부 실패)',
      `${resultMessage}\n\n실패 원인:\n${errors.slice(0, 5).join('\n')}${errors.length > 5 ? `\n... 외 ${errors.length - 5}건` : ''}`
    );
  } else {
    showSaveResultModal(
      'success',
      '일괄 제출 완료',
      resultMessage
    );
  }
};

/**
 * 날짜 포맷 함수
 */
function formatDate(dateString) {
  if (window.CommonUtils) return window.CommonUtils.formatDate(dateString);
  return formatDateForApi(dateString);
}

/**
 * 신고 상태 라벨 반환
 */
function getStatusLabel(status) {
  const labels = {
    'reported': '신고됨',
    'received': '접수됨',
    'in_progress': '처리중',
    'completed': '완료',
    'closed': '종료'
  };
  return labels[status] || status || '-';
}

/**
 * 작성 완료된 작업보고서 로드
 */
window.loadCompletedReports = async function() {
  try {
    const selectedDate = document.getElementById('completedReportDate').value;
    if (!selectedDate) {
      showMessage('날짜를 선택해주세요.', 'error');
      return;
    }

    // 해당 날짜의 작업보고서 조회
    const response = await window.apiCall(`/daily-work-reports?date=${selectedDate}`);

    console.log('완료된 보고서 API 응답:', response);

    // API 응답이 배열인지 객체인지 확인
    let reports = [];
    if (Array.isArray(response)) {
      reports = response;
    } else if (response.success && response.data) {
      reports = Array.isArray(response.data) ? response.data : [];
    } else if (response.data) {
      reports = Array.isArray(response.data) ? response.data : [];
    }

    renderCompletedReports(reports);
  } catch (error) {
    console.error('완료된 보고서 로드 오류:', error);
    showMessage('작업보고서를 불러오는 중 오류가 발생했습니다.', 'error');
  }
};

/**
 * 완료된 보고서 목록 렌더링
 */
function renderCompletedReports(reports) {
  const container = document.getElementById('completedReportsList');

  if (!reports || reports.length === 0) {
    container.innerHTML = '<p style="text-align: center; padding: 2rem; color: #9ca3af;">작성된 작업보고서가 없습니다.</p>';
    return;
  }

  const html = reports.map(report => `
    <div class="completed-report-card">
      <div class="report-header">
        <div>
          <h4>${escapeHtml(report.worker_name || '작업자')}</h4>
          ${report.tbm_session_id ? '<span class="tbm-badge">TBM 연동</span>' : '<span class="manual-badge">수동 입력</span>'}
        </div>
        <span class="report-date">${escapeHtml(formatDate(report.report_date))}</span>
      </div>

      <div class="report-info">
        <div class="info-row">
          <span class="label">프로젝트:</span>
          <span class="value">${escapeHtml(report.project_name || '-')}</span>
        </div>
        <div class="info-row">
          <span class="label">공정:</span>
          <span class="value">${escapeHtml(report.work_type_name || '-')}</span>
        </div>
        <div class="info-row">
          <span class="label">작업:</span>
          <span class="value">${escapeHtml(report.task_name || '-')}</span>
        </div>
        <div class="info-row">
          <span class="label">작업시간:</span>
          <span class="value">${parseFloat(report.total_hours || report.work_hours || 0)}시간</span>
        </div>
        ${report.regular_hours !== undefined && report.regular_hours !== null ? `
        <div class="info-row">
          <span class="label">정규 시간:</span>
          <span class="value">${parseFloat(report.regular_hours)}시간</span>
        </div>
        ` : ''}
        ${report.error_hours && report.error_hours > 0 ? `
        <div class="info-row">
          <span class="label">부적합 처리:</span>
          <span class="value" style="color: #dc2626;">${parseFloat(report.error_hours)}시간</span>
        </div>
        <div class="info-row">
          <span class="label">부적합 원인:</span>
          <span class="value">${escapeHtml(report.error_type_name || '-')}</span>
        </div>
        ` : ''}
        <div class="info-row">
          <span class="label">작성자:</span>
          <span class="value">${escapeHtml(report.created_by_name || '-')}</span>
        </div>
        ${report.start_time && report.end_time ? `
        <div class="info-row">
          <span class="label">작업 시간:</span>
          <span class="value">${escapeHtml(report.start_time)} ~ ${escapeHtml(report.end_time)}</span>
        </div>
        ` : ''}
      </div>
      <div class="report-actions" style="display: flex; gap: 0.5rem; margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid #e5e7eb;">
        <button type="button" class="btn btn-sm btn-secondary" onclick='openEditReportModal(${JSON.stringify(report).replace(/'/g, "&#39;")})' style="flex: 1; padding: 0.4rem 0.6rem; font-size: 0.75rem;">
           수정
        </button>
        <button type="button" class="btn btn-sm btn-danger" onclick="deleteWorkReport(${report.id})" style="flex: 1; padding: 0.4rem 0.6rem; font-size: 0.75rem; background: #fee2e2; color: #dc2626; border: 1px solid #fecaca;">
           삭제
        </button>
      </div>
    </div>
  `).join('');

  container.innerHTML = html;
}

/**
 * 작업보고서 수정 모달 열기
 */
window.openEditReportModal = function(report) {
  // 수정 모달이 없으면 동적 생성
  let modal = document.getElementById('editReportModal');
  if (!modal) {
    modal = document.createElement('div');
    modal.id = 'editReportModal';
    modal.className = 'modal-overlay';
    modal.style.cssText = 'display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); z-index: 1003; align-items: center; justify-content: center;';
    modal.innerHTML = `
      <div class="modal-container" style="background: white; border-radius: 8px; max-width: 500px; width: 90%; max-height: 90vh; overflow-y: auto; margin: auto; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);">
        <div class="modal-header" style="padding: 1rem 1.5rem; border-bottom: 1px solid #e5e7eb; display: flex; justify-content: space-between; align-items: center;">
          <h2 style="font-size: 1.1rem; font-weight: 600; color: #111827; margin: 0;">작업보고서 수정</h2>
          <button class="modal-close" onclick="closeEditReportModal()" style="background: none; border: none; font-size: 1.5rem; cursor: pointer; color: #6b7280;">&times;</button>
        </div>
        <div class="modal-body" style="padding: 1.5rem;">
          <form id="editReportForm">
            <input type="hidden" id="editReportId">

            <div class="form-group" style="margin-bottom: 1rem;">
              <label style="display: block; font-size: 0.875rem; font-weight: 500; margin-bottom: 0.25rem;">작업자</label>
              <input type="text" id="editWorkerName" readonly style="width: 100%; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 4px; background: #f3f4f6;">
            </div>

            <div class="form-group" style="margin-bottom: 1rem;">
              <label style="display: block; font-size: 0.875rem; font-weight: 500; margin-bottom: 0.25rem;">프로젝트</label>
              <select id="editProjectId" class="form-input" style="width: 100%; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 4px;">
                ${projects.map(p => `<option value="${p.project_id}">${escapeHtml(p.project_name)}</option>`).join('')}
              </select>
            </div>

            <div class="form-group" style="margin-bottom: 1rem;">
              <label style="display: block; font-size: 0.875rem; font-weight: 500; margin-bottom: 0.25rem;">공정</label>
              <select id="editWorkTypeId" class="form-input" style="width: 100%; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 4px;" onchange="loadTasksForEdit()">
                ${workTypes.map(wt => `<option value="${wt.id}">${escapeHtml(wt.name)}</option>`).join('')}
              </select>
            </div>

            <div class="form-group" style="margin-bottom: 1rem;">
              <label style="display: block; font-size: 0.875rem; font-weight: 500; margin-bottom: 0.25rem;">작업</label>
              <select id="editTaskId" class="form-input" style="width: 100%; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 4px;">
                <option value="">작업 선택</option>
              </select>
            </div>

            <div class="form-group" style="margin-bottom: 1rem;">
              <label style="display: block; font-size: 0.875rem; font-weight: 500; margin-bottom: 0.25rem;">작업시간 (시간)</label>
              <input type="number" id="editWorkHours" step="0.5" min="0" max="24" class="form-input" style="width: 100%; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 4px;">
            </div>

            <div class="form-group" style="margin-bottom: 1rem;">
              <label style="display: block; font-size: 0.875rem; font-weight: 500; margin-bottom: 0.25rem;">작업상태</label>
              <select id="editWorkStatusId" class="form-input" style="width: 100%; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 4px;">
                ${workStatusTypes.map(ws => `<option value="${ws.id}">${escapeHtml(ws.name)}</option>`).join('')}
              </select>
            </div>
          </form>
        </div>
        <div class="modal-footer" style="padding: 1rem 1.5rem; border-top: 1px solid #e5e7eb; display: flex; gap: 0.75rem; justify-content: flex-end;">
          <button type="button" class="btn btn-secondary" onclick="closeEditReportModal()" style="padding: 0.5rem 1rem;">취소</button>
          <button type="button" class="btn btn-primary" onclick="saveEditedReport()" style="padding: 0.5rem 1rem; background: #f59e0b; border: none; color: white; border-radius: 4px; cursor: pointer;">저장</button>
        </div>
      </div>
    `;
    document.body.appendChild(modal);
  }

  // 폼에 데이터 채우기
  document.getElementById('editReportId').value = report.id;
  document.getElementById('editWorkerName').value = report.worker_name || '작업자';
  document.getElementById('editProjectId').value = report.project_id || '';
  document.getElementById('editWorkHours').value = report.work_hours || report.total_hours || 0;
  document.getElementById('editWorkStatusId').value = report.work_status_id || 1;

  // 공정 선택 후 작업 목록 로드
  const workTypeSelect = document.getElementById('editWorkTypeId');

  // work_type_id가 실제로는 task_id를 저장하고 있으므로, task에서 work_type을 찾아야 함
  // 일단 task 기반으로 찾기 시도
  loadTasksForEdit().then(() => {
    const taskSelect = document.getElementById('editTaskId');
    // work_type_id 컬럼에 저장된 값이 실제로는 task_id
    if (report.work_type_id) {
      taskSelect.value = report.work_type_id;
    }
  });

  modal.style.display = 'flex';
};

/**
 * 수정 모달용 작업 목록 로드
 */
window.loadTasksForEdit = async function() {
  const workTypeId = document.getElementById('editWorkTypeId').value;
  const taskSelect = document.getElementById('editTaskId');

  if (!workTypeId) {
    taskSelect.innerHTML = '<option value="">공정을 먼저 선택하세요</option>';
    return;
  }

  try {
    const response = await window.apiCall(`/tasks?work_type_id=${workTypeId}`);
    const tasks = response.data || response || [];

    taskSelect.innerHTML = '<option value="">작업 선택</option>' +
      tasks.map(t => `<option value="${t.task_id}">${escapeHtml(t.task_name)}</option>`).join('');
  } catch (error) {
    console.error('작업 목록 로드 오류:', error);
    taskSelect.innerHTML = '<option value="">로드 실패</option>';
  }
};

/**
 * 수정 모달 닫기
 */
window.closeEditReportModal = function() {
  const modal = document.getElementById('editReportModal');
  if (modal) {
    modal.style.display = 'none';
  }
};

/**
 * 수정된 보고서 저장
 */
window.saveEditedReport = async function() {
  const reportId = document.getElementById('editReportId').value;
  const projectId = document.getElementById('editProjectId').value;
  const taskId = document.getElementById('editTaskId').value;
  const workHours = parseFloat(document.getElementById('editWorkHours').value);
  const workStatusId = document.getElementById('editWorkStatusId').value;

  if (!projectId || !taskId || !workHours) {
    showMessage('필수 항목을 모두 입력해주세요.', 'error');
    return;
  }

  try {
    const updateData = {
      project_id: parseInt(projectId),
      work_type_id: parseInt(taskId), // task_id가 work_type_id 컬럼에 저장됨
      work_hours: workHours,
      work_status_id: parseInt(workStatusId)
    };

    const response = await window.apiCall(`/daily-work-reports/${reportId}`, 'PUT', updateData);

    if (response.success) {
      showMessage('작업보고서가 수정되었습니다.', 'success');
      closeEditReportModal();
      loadCompletedReports(); // 목록 새로고침
    } else {
      throw new Error(response.message || '수정 실패');
    }
  } catch (error) {
    console.error('작업보고서 수정 오류:', error);
    showMessage('수정 실패: ' + error.message, 'error');
  }
};

/**
 * 작업보고서 삭제
 */
window.deleteWorkReport = async function(reportId) {
  if (!confirm('이 작업보고서를 삭제하시겠습니까?')) {
    return;
  }

  try {
    const response = await window.apiCall(`/daily-work-reports/${reportId}`, 'DELETE');

    if (response.success) {
      showMessage('작업보고서가 삭제되었습니다.', 'success');
      loadCompletedReports(); // 목록 새로고침
    } else {
      throw new Error(response.message || '삭제 실패');
    }
  } catch (error) {
    console.error('작업보고서 삭제 오류:', error);
    showMessage('삭제 실패: ' + error.message, 'error');
  }
};

// =================================================================
// 기존 함수들
// =================================================================

// 한국 시간 기준 오늘 날짜
function getKoreaToday() {
  if (window.CommonUtils) return window.CommonUtils.getTodayKST();
  const now = new Date();
  return now.getFullYear() + '-' + String(now.getMonth()+1).padStart(2,'0') + '-' + String(now.getDate()).padStart(2,'0');
}

// 현재 로그인한 사용자 정보 가져오기
function getCurrentUser() {
  // SSO 사용자 정보 우선
  if (window.getSSOUser) {
    const ssoUser = window.getSSOUser();
    if (ssoUser) return ssoUser;
  }

  try {
    const token = window.getSSOToken ? window.getSSOToken() : (localStorage.getItem('sso_token'));
    if (token) {
      const payloadBase64 = token.split('.')[1];
      if (payloadBase64) {
        return JSON.parse(atob(payloadBase64));
      }
    }
  } catch (error) {
    console.log('토큰에서 사용자 정보 추출 실패:', error);
  }

  try {
    const userInfo = localStorage.getItem('sso_user');
    if (userInfo) return JSON.parse(userInfo);
  } catch (error) {
    console.log('localStorage에서 사용자 정보 가져오기 실패:', error);
  }

  return null;
}

// 메시지 표시
function showMessage(message, type = 'info') {
  const container = document.getElementById('message-container');
  container.innerHTML = `<div class="message ${type}">${message}</div>`;

  if (type === 'success') {
    setTimeout(() => {
      hideMessage();
    }, 5000);
  }
}

function hideMessage() {
  document.getElementById('message-container').innerHTML = '';
}

// 저장 결과 모달 표시
function showSaveResultModal(type, title, message, details = null) {
  const modal = document.getElementById('saveResultModal');
  const titleElement = document.getElementById('resultModalTitle');
  const contentElement = document.getElementById('resultModalContent');

  // 아이콘 설정
  let icon = '';
  switch (type) {
    case 'success':
      icon = '';
      break;
    case 'error':
      icon = '';
      break;
    case 'warning':
      icon = '';
      break;
    default:
      icon = 'ℹ';
  }

  // 모달 내용 구성
  let content = `
    <div class="result-icon ${type}">${icon}</div>
    <h3 class="result-title ${type}">${title}</h3>
    <p class="result-message">${message}</p>
  `;

  // 상세 정보가 있으면 추가
  if (details) {
    if (Array.isArray(details) && details.length > 0) {
      content += `
        <div class="result-details">
          <h4>상세 정보:</h4>
          <ul>
            ${details.map(detail => `<li>${detail}</li>`).join('')}
          </ul>
        </div>
      `;
    } else if (typeof details === 'string') {
      content += `
        <div class="result-details">
          <p>${details}</p>
        </div>
      `;
    }
  }

  titleElement.textContent = '저장 결과';
  contentElement.innerHTML = content;
  modal.style.display = 'flex';

  // ESC 키로 닫기
  document.addEventListener('keydown', function (e) {
    if (e.key === 'Escape') {
      closeSaveResultModal();
    }
  });

  // 배경 클릭으로 닫기
  modal.addEventListener('click', function (e) {
    if (e.target === modal) {
      closeSaveResultModal();
    }
  });
}

// 저장 결과 모달 닫기
function closeSaveResultModal() {
  const modal = document.getElementById('saveResultModal');
  modal.style.display = 'none';

  // 이벤트 리스너 제거
  document.removeEventListener('keydown', closeSaveResultModal);
}

// 전역에서 접근 가능하도록 window에 할당
window.closeSaveResultModal = closeSaveResultModal;

// 단계 이동
function goToStep(stepNumber) {
  for (let i = 1; i <= 3; i++) {
    const step = document.getElementById(`step${i}`);
    if (step) {
      step.classList.remove('active', 'completed');
      if (i < stepNumber) {
        step.classList.add('completed');
        const stepNum = step.querySelector('.step-number');
        if (stepNum) stepNum.classList.add('completed');
      } else if (i === stepNumber) {
        step.classList.add('active');
      }
    }
  }

  // 진행 단계 표시 업데이트
  updateProgressSteps(stepNumber);

  currentStep = stepNumber;
}

// 진행 단계 표시 업데이트
function updateProgressSteps(currentStepNumber) {
  for (let i = 1; i <= 3; i++) {
    const progressStep = document.getElementById(`progressStep${i}`);
    if (progressStep) {
      progressStep.classList.remove('active', 'completed');

      if (i < currentStepNumber) {
        progressStep.classList.add('completed');
      } else if (i === currentStepNumber) {
        progressStep.classList.add('active');
      }
    }
  }
}

// 초기 데이터 로드 (통합 API 사용)
async function loadData() {
  try {
    showMessage('데이터를 불러오는 중...', 'loading');

    await loadWorkers();
    await loadProjects();
    await loadWorkTypes();
    await loadWorkStatusTypes();
    await loadErrorTypes();

    console.log('로드된 작업자 수:', workers.length);
    console.log('로드된 프로젝트 수:', projects.length);
    console.log('작업 유형 수:', workTypes.length);

    hideMessage();

  } catch (error) {
    console.error('데이터 로드 실패:', error);
    showMessage('데이터 로드 중 오류가 발생했습니다: ' + error.message, 'error');
  }
}

async function loadWorkers() {
  try {
    console.log('Workers API 호출 중... (통합 API 사용)');
    // 생산팀 소속 작업자만 조회
    const data = await window.apiCall(`/workers?limit=1000&department_id=1`);
    const allWorkers = Array.isArray(data) ? data : (data.data || data.workers || []);

    // 작업 보고서에 표시할 작업자만 필터링
    // 퇴사자만 제외 (계정 여부와 무관하게 재직자는 모두 표시)
    workers = allWorkers.filter(worker => {
      const notResigned = worker.employment_status !== 'resigned';
      return notResigned;
    });

  } catch (error) {
    console.error('작업자 로딩 오류:', error);
    throw error;
  }
}

async function loadProjects() {
  try {
    console.log('Projects API 호출 중... (활성 프로젝트만)');
    const data = await window.apiCall(`/projects/active/list`);
    projects = Array.isArray(data) ? data : (data.data || data.projects || []);
  } catch (error) {
    console.error('프로젝트 로딩 오류:', error);
    throw error;
  }
}

async function loadWorkTypes() {
  try {
    const response = await window.apiCall(`/daily-work-reports/work-types`);
    const data = response.data || response;
    if (Array.isArray(data) && data.length > 0) {
      workTypes = data;
      return;
    }
    throw new Error('API 실패');
  } catch (error) {
    workTypes = [
      { id: 1, name: 'Base' },
      { id: 2, name: 'Vessel' },
      { id: 3, name: 'Piping' }
    ];
  }
}

async function loadWorkStatusTypes() {
  try {
    const response = await window.apiCall(`/daily-work-reports/work-status-types`);
    const data = response.data || response;
    if (Array.isArray(data) && data.length > 0) {
      workStatusTypes = data;
      return;
    }
    throw new Error('API 실패');
  } catch (error) {
    workStatusTypes = [
      { id: 1, name: '정규' },
      { id: 2, name: '에러' }
    ];
  }
}

async function loadErrorTypes() {
  // 레거시 에러 유형 로드 (호환성)
  try {
    const response = await window.apiCall(`/daily-work-reports/error-types`);
    const data = response.data || response;
    if (Array.isArray(data) && data.length > 0) {
      errorTypes = data;
    }
  } catch (error) {
    errorTypes = [];
  }

  // 신고 카테고리 로드 (부적합 유형만)
  try {
    const catResponse = await window.apiCall('/work-issues/categories/type/nonconformity');
    if (catResponse && catResponse.success && Array.isArray(catResponse.data)) {
      issueCategories = catResponse.data;

      // 모든 아이템 로드
      const itemResponse = await window.apiCall('/work-issues/items');
      if (itemResponse && itemResponse.success && Array.isArray(itemResponse.data)) {
        // 부적합 카테고리의 아이템만 필터링
        const categoryIds = issueCategories.map(c => c.category_id);
        issueItems = itemResponse.data.filter(item => categoryIds.includes(item.category_id));
      }
    }
  } catch (error) {
    issueCategories = [];
    issueItems = [];
  }
}

// TBM 팀 구성 자동 불러오기
async function loadTbmTeamForDate(date) {
  try {
    const response = await window.apiCall(`/tbm/sessions/date/${date}`);

    if (response && response.success && response.data && response.data.length > 0) {
      // 가장 최근 세션 선택 (진행중인 세션 우선)
      const draftSessions = response.data.filter(s => s.status === 'draft');
      const targetSession = draftSessions.length > 0 ? draftSessions[0] : response.data[0];

      if (targetSession) {
        // 팀 구성 조회
        const teamRes = await window.apiCall(`/tbm/sessions/${targetSession.session_id}/team`);
        if (teamRes && teamRes.success && teamRes.data) {
          const teamWorkerIds = teamRes.data.map(m => m.user_id);
          return teamWorkerIds;
        }
      }
    }

    return [];
  } catch (error) {
    console.error(' TBM 팀 구성 조회 오류:', error);
    return [];
  }
}

// 작업자 그리드 생성
async function populateWorkerGrid() {
  const grid = document.getElementById('workerGrid');
  grid.innerHTML = '';

  // 선택된 날짜의 TBM 팀 구성 불러오기
  const reportDate = document.getElementById('reportDate').value;
  let tbmWorkerIds = [];

  if (reportDate) {
    tbmWorkerIds = await loadTbmTeamForDate(reportDate);
  }

  // TBM 팀 구성이 있으면 안내 메시지 표시
  if (tbmWorkerIds.length > 0) {
    const infoDiv = document.createElement('div');
    infoDiv.style.cssText = `
      padding: 1rem;
      background: #eff6ff;
      border: 1px solid #3b82f6;
      border-radius: 0.5rem;
      margin-bottom: 1rem;
      color: #1e40af;
      font-size: 0.875rem;
    `;
    infoDiv.innerHTML = `
      <strong> TBM 팀 구성 자동 적용</strong><br>
      오늘 TBM에서 구성된 팀원 ${tbmWorkerIds.length}명이 자동으로 선택되었습니다.
    `;
    grid.appendChild(infoDiv);
  }

  workers.forEach(worker => {
    const btn = document.createElement('button');
    btn.type = 'button';
    btn.className = 'worker-card';
    btn.textContent = worker.worker_name;
    btn.dataset.id = worker.user_id;

    // TBM 팀 구성에 포함된 작업자는 자동 선택
    if (tbmWorkerIds.includes(worker.user_id)) {
      btn.classList.add('selected');
      selectedWorkers.add(worker.user_id);
    }

    btn.addEventListener('click', () => {
      toggleWorkerSelection(worker.user_id, btn);
    });

    grid.appendChild(btn);
  });

  // 자동 선택된 작업자가 있으면 다음 단계 버튼 활성화
  const nextBtn = document.getElementById('nextStep2');
  if (nextBtn) {
    nextBtn.disabled = selectedWorkers.size === 0;
  }
}

// 작업자 선택 토글
function toggleWorkerSelection(workerId, btnElement) {
  if (selectedWorkers.has(workerId)) {
    selectedWorkers.delete(workerId);
    btnElement.classList.remove('selected');
  } else {
    selectedWorkers.add(workerId);
    btnElement.classList.add('selected');
  }

  const nextBtn = document.getElementById('nextStep2');
  nextBtn.disabled = selectedWorkers.size === 0;
}

// 작업 항목 추가
function addWorkEntry() {
  const container = document.getElementById('workEntriesList');
  workEntryCounter++;

  const entryDiv = document.createElement('div');
  entryDiv.className = 'work-entry';
  entryDiv.dataset.id = workEntryCounter;

  entryDiv.innerHTML = `
    <div class="work-entry-header">
      <div class="work-entry-title">작업 항목 #${workEntryCounter}</div>
      <button type="button" class="remove-work-btn" onclick="event.stopPropagation(); removeWorkEntry(${workEntryCounter})" title="이 작업 삭제">
         삭제
      </button>
    </div>
    
    <div class="work-entry-grid">
      <div class="form-field-group">
        <div class="form-field-label">
          <span class="form-field-icon"></span>
          프로젝트
        </div>
        <select class="form-select project-select" required>
          <option value="">프로젝트를 선택하세요</option>
          ${projects.map(p => `<option value="${escapeHtml(String(p.project_id))}">${escapeHtml(p.project_name)}</option>`).join('')}
        </select>
      </div>

      <div class="form-field-group">
        <div class="form-field-label">
          <span class="form-field-icon"></span>
          작업 유형
        </div>
        <select class="form-select work-type-select" required>
          <option value="">작업 유형을 선택하세요</option>
          ${workTypes.map(wt => `<option value="${escapeHtml(String(wt.id))}">${escapeHtml(wt.name)}</option>`).join('')}
        </select>
      </div>
    </div>

    <div class="work-entry-full">
      <div class="form-field-group">
        <div class="form-field-label">
          <span class="form-field-icon"></span>
          업무 상태
        </div>
        <select class="form-select work-status-select" required>
          <option value="">업무 상태를 선택하세요</option>
          ${workStatusTypes.map(ws => `<option value="${escapeHtml(String(ws.id))}">${escapeHtml(ws.name)}</option>`).join('')}
        </select>
      </div>
    </div>
    
    <div class="error-type-section work-entry-full">
      <div class="form-field-label">
        <span class="form-field-icon"></span>
        에러 유형
      </div>
      <select class="form-select error-type-select">
        <option value="">에러 유형을 선택하세요</option>
        ${errorTypes.map(et => `<option value="${et.id}">${et.name}</option>`).join('')}
      </select>
    </div>
    
    <div class="time-input-section work-entry-full">
      <div class="form-field-label">
        <span class="form-field-icon"></span>
        작업 시간 (시간)
      </div>
      <input type="number" class="form-select time-input" 
             placeholder="작업 시간을 입력하세요" 
             min="0.25" 
             max="24" 
             step="0.25" 
             value="1.00"
             required>
      <div class="quick-time-buttons">
        <button type="button" class="quick-time-btn" data-hours="0.5">30분</button>
        <button type="button" class="quick-time-btn" data-hours="1">1시간</button>
        <button type="button" class="quick-time-btn" data-hours="2">2시간</button>
        <button type="button" class="quick-time-btn" data-hours="4">4시간</button>
        <button type="button" class="quick-time-btn" data-hours="8">8시간</button>
      </div>
    </div>
  `;

  container.appendChild(entryDiv);

  setupWorkEntryEvents(entryDiv);
}

// 작업 항목 이벤트 설정
function setupWorkEntryEvents(entryDiv) {
  const timeInput = entryDiv.querySelector('.time-input');
  const workStatusSelect = entryDiv.querySelector('.work-status-select');
  const errorTypeSection = entryDiv.querySelector('.error-type-section');
  const errorTypeSelect = entryDiv.querySelector('.error-type-select');

  // 시간 입력 이벤트
  timeInput.addEventListener('input', updateTotalHours);

  // 빠른 시간 버튼 이벤트
  entryDiv.querySelectorAll('.quick-time-btn').forEach(btn => {
    btn.addEventListener('click', (e) => {
      e.preventDefault();
      timeInput.value = btn.dataset.hours;
      updateTotalHours();

      // 버튼 클릭 효과
      btn.style.transform = 'scale(0.95)';
      setTimeout(() => {
        btn.style.transform = '';
      }, 150);
    });
  });

  // 업무 상태 변경 시 에러 유형 섹션 토글
  workStatusSelect.addEventListener('change', (e) => {
    const isError = e.target.value === '2'; // 에러 상태 ID가 2라고 가정

    if (isError) {
      errorTypeSection.classList.add('visible');
      errorTypeSelect.required = true;

      // 에러 상태일 때 시각적 피드백
      errorTypeSection.style.animation = 'slideDown 0.4s ease-out';
    } else {
      errorTypeSection.classList.remove('visible');
      errorTypeSelect.required = false;
      errorTypeSelect.value = '';
    }
  });

  // 폼 필드 포커스 효과
  entryDiv.querySelectorAll('.form-field-group').forEach(group => {
    const input = group.querySelector('select, input');
    if (input) {
      input.addEventListener('focus', () => {
        group.classList.add('focused');
      });

      input.addEventListener('blur', () => {
        group.classList.remove('focused');
      });
    }
  });
}

// 작업 항목 제거
function removeWorkEntry(id) {
  const entry = document.querySelector(`.work-entry[data-id="${id}"]`);
  if (entry) {
    entry.remove();
    updateTotalHours();
  } else {
  }
}

// 총 시간 업데이트
function updateTotalHours() {
  const timeInputs = document.querySelectorAll('.time-input');
  let total = 0;

  timeInputs.forEach(input => {
    const value = parseFloat(input.value) || 0;
    total += value;
  });

  const display = document.getElementById('totalHoursDisplay');
  display.textContent = `총 작업시간: ${total}시간`;

  if (total > 24) {
    display.style.background = 'linear-gradient(135deg, #e74c3c 0%, #c0392b 100%)';
    display.textContent += '24시간 초과';
  } else {
    display.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
  }
}

// 저장 함수 (통합 API 사용)
async function saveWorkReport() {
  const reportDate = document.getElementById('reportDate').value;

  if (!reportDate || selectedWorkers.size === 0) {
    showSaveResultModal(
      'error',
      '입력 오류',
      '날짜와 작업자를 선택해주세요.'
    );
    return;
  }

  const entries = document.querySelectorAll('.work-entry');

  if (entries.length === 0) {
    showSaveResultModal(
      'error',
      '작업 항목 없음',
      '최소 하나의 작업을 추가해주세요.'
    );
    return;
  }

  const newWorkEntries = [];

  for (const entry of entries) {

    const projectSelect = entry.querySelector('.project-select');
    const workTypeSelect = entry.querySelector('.work-type-select');
    const workStatusSelect = entry.querySelector('.work-status-select');
    const errorTypeSelect = entry.querySelector('.error-type-select');
    const timeInput = entry.querySelector('.time-input');

    console.log(' 선택된 요소들:', {
      projectSelect,
      workTypeSelect,
      workStatusSelect,
      errorTypeSelect,
      timeInput
    });

    const projectId = projectSelect?.value;
    const workTypeId = workTypeSelect?.value;
    const workStatusId = workStatusSelect?.value;
    const errorTypeId = errorTypeSelect?.value;
    const workHours = timeInput?.value;

    console.log(' 수집된 값들:', {
      projectId,
      workTypeId,
      workStatusId,
      errorTypeId,
      workHours
    });

    if (!projectId || !workTypeId || !workStatusId || !workHours) {
      showSaveResultModal(
        'error',
        '입력 오류',
        '모든 작업 항목을 완성해주세요.'
      );
      return;
    }

    if (workStatusId === '2' && !errorTypeId) {
      showSaveResultModal(
        'error',
        '입력 오류',
        '에러 상태인 경우 에러 유형을 선택해주세요.'
      );
      return;
    }

    const workEntry = {
      project_id: parseInt(projectId),
      work_type_id: parseInt(workTypeId),
      work_status_id: parseInt(workStatusId),
      error_type_id: errorTypeId ? parseInt(errorTypeId) : null,
      work_hours: parseFloat(workHours)
    };

    console.log(' 작업 항목 상세:', {
      project_id: workEntry.project_id,
      work_type_id: workEntry.work_type_id,
      work_status_id: workEntry.work_status_id,
      error_type_id: workEntry.error_type_id,
      work_hours: workEntry.work_hours
    });
    newWorkEntries.push(workEntry);
  }


  try {
    const submitBtn = document.getElementById('submitBtn');
    submitBtn.disabled = true;
    submitBtn.textContent = ' 저장 중...';

    const currentUser = getCurrentUser();
    let totalSaved = 0;
    let totalFailed = 0;
    const failureDetails = [];

    for (const workerId of selectedWorkers) {
      const workerName = workers.find(w => w.user_id == workerId)?.worker_name || '알 수 없음';

      // 서버가 기대하는 work_entries 배열 형태로 전송
      const requestData = {
        report_date: reportDate,
        user_id: parseInt(workerId),
        work_entries: newWorkEntries.map(entry => ({
          project_id: entry.project_id,
          task_id: entry.work_type_id, // 서버에서 task_id로 기대
          work_hours: entry.work_hours,
          work_status_id: entry.work_status_id,
          error_type_id: entry.error_type_id
        })),
        created_by: currentUser?.user_id || currentUser?.id
      };


      try {
        const result = await window.apiCall(`/daily-work-reports`, 'POST', requestData);

        totalSaved++;
      } catch (error) {
        console.error(' 저장 실패:', error);
        totalFailed++;

        failureDetails.push(`${workerName}: ${error.message}`);
      }
    }

    // 결과 모달 표시
    if (totalSaved > 0 && totalFailed === 0) {
      showSaveResultModal(
        'success',
        '저장 완료!',
        `${totalSaved}명의 작업보고서가 성공적으로 저장되었습니다.`
      );
    } else if (totalSaved > 0 && totalFailed > 0) {
      showSaveResultModal(
        'warning',
        '부분 저장 완료',
        `${totalSaved}명은 성공했지만 ${totalFailed}명은 실패했습니다.`,
        failureDetails
      );
    } else {
      showSaveResultModal(
        'error',
        '저장 실패',
        '모든 작업보고서 저장이 실패했습니다.',
        failureDetails
      );
    }

    if (totalSaved > 0) {
      setTimeout(() => {
        refreshTodayWorkers();
        resetForm();
      }, 2000);
    }

  } catch (error) {
    console.error('저장 오류:', error);
    showSaveResultModal(
      'error',
      '저장 오류',
      '저장 중 예기치 못한 오류가 발생했습니다.',
      [error.message]
    );
  } finally {
    const submitBtn = document.getElementById('submitBtn');
    submitBtn.disabled = false;
    submitBtn.textContent = ' 작업보고서 저장';
  }
}

// 폼 초기화
function resetForm() {
  goToStep(1);

  selectedWorkers.clear();
  document.querySelectorAll('.worker-card.selected').forEach(btn => {
    btn.classList.remove('selected');
  });

  const container = document.getElementById('workEntriesList');
  container.innerHTML = '';

  workEntryCounter = 0;
  updateTotalHours();

  document.getElementById('nextStep2').disabled = true;
}

// 당일 작업자 현황 로드 (본인 입력분만) - 통합 API 사용
async function loadTodayWorkers() {
  const section = document.getElementById('dailyWorkersSection');
  const content = document.getElementById('dailyWorkersContent');

  if (!section || !content) {
    console.log('당일 현황 섹션이 HTML에 없습니다.');
    return;
  }

  try {
    const today = getKoreaToday();
    const currentUser = getCurrentUser();

    content.innerHTML = '<div class="loading-spinner"> 내가 입력한 오늘의 작업 현황을 불러오는 중... (통합 API)</div>';
    section.style.display = 'block';

    // 본인이 입력한 데이터만 조회 (통합 API 사용)
    let queryParams = `date=${today}`;
    if (currentUser?.user_id) {
      queryParams += `&created_by=${currentUser.user_id}`;
    } else if (currentUser?.id) {
      queryParams += `&created_by=${currentUser.id}`;
    }


    const rawData = await window.apiCall(`/daily-work-reports?${queryParams}`);

    let data = [];
    if (Array.isArray(rawData)) {
      data = rawData;
    } else if (rawData?.data) {
      data = rawData.data;
    }

    displayMyDailyWorkers(data, today);

  } catch (error) {
    console.error('당일 작업자 로드 오류:', error);
    content.innerHTML = `
      <div class="no-data-message">
         오늘의 작업 현황을 불러올 수 없습니다.<br>
        <small>${error.message}</small>
      </div>
    `;
  }
}

// 본인 입력 작업자 현황 표시 (수정/삭제 기능 포함)
function displayMyDailyWorkers(data, date) {
  const content = document.getElementById('dailyWorkersContent');

  if (!Array.isArray(data) || data.length === 0) {
    content.innerHTML = `
      <div class="no-data-message">
         내가 오늘(${date}) 입력한 작업이 없습니다.<br>
        <small>새로운 작업을 추가해보세요!</small>
      </div>
    `;
    return;
  }

  // 작업자별로 데이터 그룹화
  const workerGroups = {};
  data.forEach(work => {
    const workerName = work.worker_name || '미지정';
    if (!workerGroups[workerName]) {
      workerGroups[workerName] = [];
    }
    workerGroups[workerName].push(work);
  });

  const totalWorkers = Object.keys(workerGroups).length;
  const totalWorks = data.length;

  const headerHtml = `
    <div class="daily-workers-header">
      <h4> 내가 입력한 오늘(${escapeHtml(date)}) 작업 현황 - 총 ${parseInt(totalWorkers) || 0}명, ${parseInt(totalWorks) || 0}개 작업</h4>
      <button class="refresh-btn" onclick="refreshTodayWorkers()">
         새로고침
      </button>
    </div>
  `;

  const workersHtml = Object.entries(workerGroups).map(([workerName, works]) => {
    const totalHours = works.reduce((sum, work) => {
      return sum + parseFloat(work.work_hours || 0);
    }, 0);

    // 개별 작업 항목들 (수정/삭제 버튼 포함)
    const individualWorksHtml = works.map((work) => {
      const projectName = escapeHtml(work.project_name || '미지정');
      const workTypeName = escapeHtml(work.work_type_name || '미지정');
      const workStatusName = escapeHtml(work.work_status_name || '미지정');
      const workHours = parseFloat(work.work_hours || 0);
      const errorTypeName = work.error_type_name ? escapeHtml(work.error_type_name) : null;
      const workId = parseInt(work.id) || 0;

      return `
        <div class="individual-work-item">
          <div class="work-details-grid">
            <div class="detail-item">
              <div class="detail-label"> 프로젝트</div>
              <div class="detail-value">${projectName}</div>
            </div>
            <div class="detail-item">
              <div class="detail-label"> 작업종류</div>
              <div class="detail-value">${workTypeName}</div>
            </div>
            <div class="detail-item">
              <div class="detail-label"> 작업상태</div>
              <div class="detail-value">${workStatusName}</div>
            </div>
            <div class="detail-item">
              <div class="detail-label"> 작업시간</div>
              <div class="detail-value">${workHours}시간</div>
            </div>
            ${errorTypeName ? `
            <div class="detail-item">
              <div class="detail-label"> 에러유형</div>
              <div class="detail-value">${errorTypeName}</div>
            </div>
            ` : ''}
          </div>
          <div class="action-buttons">
            <button class="edit-btn" onclick="editWorkItem('${workId}')">
               수정
            </button>
            <button class="delete-btn" onclick="deleteWorkItem('${workId}')">
               삭제
            </button>
          </div>
        </div>
      `;
    }).join('');

    return `
      <div class="worker-status-item">
        <div class="worker-header">
          <div class="worker-name"> ${escapeHtml(workerName)}</div>
          <div class="worker-total-hours">총 ${parseFloat(totalHours)}시간</div>
        </div>
        <div class="individual-works-container">
          ${individualWorksHtml}
        </div>
      </div>
    `;
  }).join('');

  content.innerHTML = headerHtml + '<div class="worker-status-grid">' + workersHtml + '</div>';
}

// 작업 항목 수정 함수 (통합 API 사용)
async function editWorkItem(workId) {
  try {
    console.log('수정할 작업 ID:', workId);

    // 1. 기존 데이터 조회 (통합 API 사용)
    showMessage('작업 정보를 불러오는 중... (통합 API)', 'loading');

    const workData = await window.apiCall(`/daily-work-reports/${workId}`);
    console.log('수정할 작업 데이터 (통합 API):', workData);

    // 2. 수정 모달 표시
    showEditModal(workData);
    hideMessage();

  } catch (error) {
    console.error('작업 정보 조회 오류:', error);
    showMessage('작업 정보를 불러올 수 없습니다: ' + error.message, 'error');
  }
}

// 수정 모달 표시
function showEditModal(workData) {
  editingWorkId = workData.id;

  const modalHtml = `
    <div class="edit-modal" id="editModal">
      <div class="edit-modal-content">
        <div class="edit-modal-header">
          <h3> 작업 수정</h3>
          <button class="close-modal-btn" onclick="closeEditModal()">×</button>
        </div>
        <div class="edit-modal-body">
          <div class="edit-form-group">
            <label> 프로젝트</label>
            <select class="edit-select" id="editProject">
              <option value="">프로젝트 선택</option>
              ${projects.map(p => `
                <option value="${p.project_id}" ${p.project_id == workData.project_id ? 'selected' : ''}>
                  ${p.project_name}
                </option>
              `).join('')}
            </select>
          </div>
          
          <div class="edit-form-group">
            <label> 작업 유형</label>
            <select class="edit-select" id="editWorkType">
              <option value="">작업 유형 선택</option>
              ${workTypes.map(wt => `
                <option value="${wt.id}" ${wt.id == workData.work_type_id ? 'selected' : ''}>
                  ${wt.name}
                </option>
              `).join('')}
            </select>
          </div>
          
          <div class="edit-form-group">
            <label> 업무 상태</label>
            <select class="edit-select" id="editWorkStatus">
              <option value="">업무 상태 선택</option>
              ${workStatusTypes.map(ws => `
                <option value="${ws.id}" ${ws.id == workData.work_status_id ? 'selected' : ''}>
                  ${ws.name}
                </option>
              `).join('')}
            </select>
          </div>
          
          <div class="edit-form-group" id="editErrorTypeGroup" style="${workData.work_status_id == 2 ? '' : 'display: none;'}">
            <label> 에러 유형</label>
            <select class="edit-select" id="editErrorType">
              <option value="">에러 유형 선택</option>
              ${errorTypes.map(et => `
                <option value="${et.id}" ${et.id == workData.error_type_id ? 'selected' : ''}>
                  ${et.name}
                </option>
              `).join('')}
            </select>
          </div>
          
          <div class="edit-form-group">
            <label> 작업 시간</label>
            <input type="number" class="edit-input" id="editWorkHours" 
                   value="${workData.work_hours}" 
                   min="0" max="24" step="0.5">
          </div>
        </div>
        <div class="edit-modal-footer">
          <button class="btn btn-secondary" onclick="closeEditModal()">취소</button>
          <button class="btn btn-success" onclick="saveEditedWork()"> 저장</button>
        </div>
      </div>
    </div>
  `;

  document.body.insertAdjacentHTML('beforeend', modalHtml);

  // 업무 상태 변경 이벤트
  document.getElementById('editWorkStatus').addEventListener('change', (e) => {
    const errorTypeGroup = document.getElementById('editErrorTypeGroup');
    if (e.target.value === '2') {
      errorTypeGroup.style.display = 'block';
    } else {
      errorTypeGroup.style.display = 'none';
    }
  });
}

// 수정 모달 닫기
function closeEditModal() {
  const modal = document.getElementById('editModal');
  if (modal) {
    modal.remove();
  }
  editingWorkId = null;
}

// 수정된 작업 저장 (통합 API 사용)
async function saveEditedWork() {
  try {
    const projectId = document.getElementById('editProject').value;
    const workTypeId = document.getElementById('editWorkType').value;
    const workStatusId = document.getElementById('editWorkStatus').value;
    const errorTypeId = document.getElementById('editErrorType').value;
    const workHours = document.getElementById('editWorkHours').value;

    if (!projectId || !workTypeId || !workStatusId || !workHours) {
      showMessage('모든 필수 항목을 입력해주세요.', 'error');
      return;
    }

    if (workStatusId === '2' && !errorTypeId) {
      showMessage('에러 상태인 경우 에러 유형을 선택해주세요.', 'error');
      return;
    }

    const updateData = {
      project_id: parseInt(projectId),
      work_type_id: parseInt(workTypeId),
      work_status_id: parseInt(workStatusId),
      error_type_id: errorTypeId ? parseInt(errorTypeId) : null,
      work_hours: parseFloat(workHours)
    };

    showMessage('작업을 수정하는 중... (통합 API)', 'loading');

    const result = await window.apiCall(`/daily-work-reports/${editingWorkId}`, {
      method: 'PUT',
      body: JSON.stringify(updateData)
    });

    showMessage(' 작업이 성공적으로 수정되었습니다!', 'success');

    closeEditModal();
    refreshTodayWorkers();

  } catch (error) {
    console.error(' 수정 실패:', error);
    showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error');
  }
}

// 작업 항목 삭제 함수 (통합 API 사용)
async function deleteWorkItem(workId) {
  if (!confirm('정말로 이 작업을 삭제하시겠습니까?\n삭제된 작업은 복구할 수 없습니다.')) {
    return;
  }

  try {
    console.log('삭제할 작업 ID:', workId);

    showMessage('작업을 삭제하는 중... (통합 API)', 'loading');

    // 개별 항목 삭제 API 호출 (본인 작성분만 삭제 가능) - 통합 API 사용
    const result = await window.apiCall(`/daily-work-reports/my-entry/${workId}`, {
      method: 'DELETE'
    });

    showMessage(' 작업이 성공적으로 삭제되었습니다!', 'success');

    // 화면 새로고침
    refreshTodayWorkers();

  } catch (error) {
    console.error(' 삭제 실패:', error);
    showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error');
  }
}

// 오늘 현황 새로고침
function refreshTodayWorkers() {
  loadTodayWorkers();
}

// 이벤트 리스너 설정 (이제 테이블 기반 UI를 사용하므로 별도 리스너 불필요)
function setupEventListeners() {
  // 기존 단계별 입력 UI 제거됨
  // 모든 이벤트는 onclick 핸들러로 직접 처리
}

// 초기화
async function init() {
  try {
    // app-init.js(defer)가 토큰/apiCall 설정 완료할 때까지 대기
    if (window.waitForApi) {
      await window.waitForApi(8000);
    } else if (!window.apiCall) {
      // waitForApi 없으면 간단 폴링
      await new Promise((resolve, reject) => {
        let elapsed = 0;
        const iv = setInterval(() => { elapsed += 50; if (window.apiCall) { clearInterval(iv); resolve(); } else if (elapsed >= 8000) { clearInterval(iv); reject(new Error('apiCall timeout')); } }, 50);
      });
    }

    await loadData();
    setupEventListeners();

    // TBM 작업 목록 로드 (기본 탭)
    await loadIncompleteTbms();


  } catch (error) {
    console.error('초기화 오류:', error);
    showMessage('초기화 중 오류가 발생했습니다.', 'error');
  }
}

// 페이지 로드 시 초기화 (module 스크립트는 DOMContentLoaded 이후 실행될 수 있음)
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', init);
} else {
  init();
}

// 전역 함수로 노출
window.removeWorkEntry = removeWorkEntry;
window.refreshTodayWorkers = refreshTodayWorkers;
window.editWorkItem = editWorkItem;
window.deleteWorkItem = deleteWorkItem;
window.closeEditModal = closeEditModal;
window.saveEditedWork = saveEditedWork;
// =================================================================
// 시간 선택 팝오버 관련 함수
// =================================================================

/**
 * 시간 포맷팅 함수
 */
function formatHours(hours) {
  const h = Math.floor(hours);
  const m = (hours % 1) * 60;
  if (m === 0) return `${h}시간`;
  return `${h}시간 ${m}분`;
}

/**
 * 시간 선택 팝오버 열기
 */
window.openTimePicker = function(index, type) {
  currentEditingField = { index, type };
  
  // 현재 값 가져오기
  const inputId = type === 'total' ? `totalHours_${index}` : `errorHours_${index}`;
  const hiddenInput = document.getElementById(inputId);
  currentTimeValue = parseFloat(hiddenInput?.value) || 0;
  
  // 팝오버 표시
  const overlay = document.getElementById('timePickerOverlay');
  const title = document.getElementById('timePickerTitle');
  
  title.textContent = type === 'total' ? '작업시간 선택' : '부적합 시간 선택';
  updateTimeDisplay();
  
  overlay.style.display = 'flex';
  
  // ESC 키로 닫기
  document.addEventListener('keydown', handleEscapeKey);
};

/**
 * ESC 키 핸들러
 */
function handleEscapeKey(e) {
  if (e.key === 'Escape') {
    closeTimePicker();
  }
}

/**
 * 시간 값 설정
 */
window.setTimeValue = function(hours) {
  currentTimeValue = hours;
  updateTimeDisplay();
};

/**
 * 시간 조정 (±30분)
 */
window.adjustTime = function(delta) {
  currentTimeValue = Math.max(0, Math.min(24, currentTimeValue + delta));
  updateTimeDisplay();
};

/**
 * 시간 표시 업데이트
 */
function updateTimeDisplay() {
  const display = document.getElementById('currentTimeDisplay');
  if (display) {
    display.textContent = formatHours(currentTimeValue);
  }
}

/**
 * 시간 선택 확인
 */
window.confirmTimeSelection = function() {
  if (!currentEditingField) return;

  const { index, type, defectIndex, issueReportId } = currentEditingField;

  // 이슈 기반 부적합 시간 선택인 경우
  if (type === 'issueDefect') {
    if (tempDefects[index] && tempDefects[index][defectIndex] !== undefined) {
      tempDefects[index][defectIndex].defect_hours = currentTimeValue;

      // 시간 표시 업데이트
      const timeDisplay = document.getElementById(`issueDefectTime_${index}_${issueReportId}`);
      if (timeDisplay) {
        timeDisplay.textContent = currentTimeValue;
      }

      // 요약 및 hidden 필드 업데이트
      updateDefectSummary(index);
      updateHiddenDefectFields(index);
    }
    closeTimePicker();
    return;
  }

  // 레거시 부적합 시간 선택인 경우
  if (type === 'defect') {
    if (tempDefects[index] && tempDefects[index][defectIndex] !== undefined) {
      tempDefects[index][defectIndex].defect_hours = currentTimeValue;

      // 시간 표시 업데이트
      const timeDisplay = document.getElementById(`defectTime_${index}_${defectIndex}`);
      if (timeDisplay) {
        timeDisplay.textContent = currentTimeValue;
      }

      // 요약 및 hidden 필드 업데이트
      updateDefectSummary(index);
      updateHiddenDefectFields(index);
    }
    closeTimePicker();
    return;
  }

  // 기존 total/error 시간 선택
  const inputId = type === 'total' ? `totalHours_${index}` : `errorHours_${index}`;
  const displayId = type === 'total' ? `totalHoursDisplay_${index}` : `errorHoursDisplay_${index}`;

  // hidden input 값 설정
  const hiddenInput = document.getElementById(inputId);
  if (hiddenInput) {
    hiddenInput.value = currentTimeValue;
  }

  // 표시 영역 업데이트
  const displayDiv = document.getElementById(displayId);
  if (displayDiv) {
    displayDiv.textContent = formatHours(currentTimeValue);
    displayDiv.classList.remove('placeholder');
    displayDiv.classList.add('has-value');
  }

  // 부적합 시간 입력 시 에러 타입 토글 (기존 방식 - 이제 사용안함)
  if (type === 'error') {
    if (index.toString().startsWith('manual_')) {
      toggleManualErrorType(index);
    } else {
      calculateRegularHours(index);
    }
  }

  closeTimePicker();
};

/**
 * 시간 선택 팝오버 닫기
 */
window.closeTimePicker = function() {
  const overlay = document.getElementById('timePickerOverlay');
  if (overlay) {
    overlay.style.display = 'none';
  }

  currentEditingField = null;
  currentTimeValue = 0;

  // ESC 키 리스너 제거
  document.removeEventListener('keydown', handleEscapeKey);
};

// =================================================================
// 부적합 원인 관리 (인라인 방식)
// =================================================================

/**
 * 부적합 영역 토글
 * - 신고된 이슈 목록 표시
 */
window.toggleDefectArea = function(index) {
  const defectRow = document.getElementById(`defectRow_${index}`);
  if (!defectRow) return;

  const isVisible = defectRow.style.display !== 'none';

  if (isVisible) {
    // 숨기기
    defectRow.style.display = 'none';
  } else {
    // 보이기 - 부적합 원인이 없으면 자동으로 하나 추가
    if (!tempDefects[index] || tempDefects[index].length === 0) {
      tempDefects[index] = [{
        issue_report_id: null,
        category_id: null,
        item_id: null,
        error_type_id: '', // 레거시 호환
        defect_hours: 0,
        note: ''
      }];
    }
    renderInlineDefectList(index);
    defectRow.style.display = '';
  }
};

/**
 * 인라인 부적합 목록 렌더링
 * - 해당 날짜에 신고된 이슈 목록을 표시
 * - 이슈 선택 → 시간 입력 방식
 */
function renderInlineDefectList(index) {
  const listContainer = document.getElementById(`defectList_${index}`);
  if (!listContainer) return;

  // 해당 TBM의 날짜 가져오기
  const tbm = incompleteTbms[index];
  const dateStr = tbm ? formatDateForApi(tbm.session_date) : null;
  const issues = dateStr ? (dailyIssuesCache[dateStr] || []) : [];

  // 작업장소 정보 가져오기
  const workerWorkplaceId = tbm?.workplace_id;
  const workerWorkplaceName = tbm?.workplace_name;

  // 부적합 유형 + 작업장소 일치하는 것만 필터링
  const nonconformityIssues = issues.filter(i => {
    // 부적합 유형만
    if (i.category_type !== 'nonconformity') return false;

    // 작업장소 매칭 (workplace_id 우선, 없으면 이름 비교)
    if (workerWorkplaceId && i.workplace_id) {
      return i.workplace_id === workerWorkplaceId;
    }
    if (workerWorkplaceName && (i.workplace_name || i.custom_location)) {
      const issueLocation = i.workplace_name || i.custom_location || '';
      return issueLocation.includes(workerWorkplaceName) || workerWorkplaceName.includes(issueLocation);
    }
    // 작업장소 정보가 없으면 포함하지 않음
    return false;
  });

  const defects = tempDefects[index] || [];


  // 이슈가 있으면 이슈 선택 UI, 없으면 레거시 UI
  if (nonconformityIssues.length > 0) {
    // 이슈 선택 방식 UI
    let html = `
      <div class="defect-issue-section">
        <div class="defect-issue-header">
          <span class="defect-issue-title"> ${escapeHtml(workerWorkplaceName || '작업장소')} 관련 부적합</span>
          <span class="defect-issue-count">${parseInt(nonconformityIssues.length) || 0}건</span>
        </div>
        <div class="defect-issue-list">
    `;

    nonconformityIssues.forEach(issue => {
      // 이 이슈가 이미 선택되었는지 확인
      const existingDefect = defects.find(d => d.issue_report_id == issue.report_id);
      const isSelected = !!existingDefect;
      const defectHours = existingDefect?.defect_hours || 0;

      // 아이템명과 추가설명 조합
      let itemText = issue.issue_item_name || '';
      if (issue.additional_description) {
        itemText = itemText ? `${itemText} - ${issue.additional_description}` : issue.additional_description;
      }

      const safeReportId = parseInt(issue.report_id) || 0;
      html += `
        <div class="defect-issue-item ${isSelected ? 'selected' : ''}" data-issue-id="${safeReportId}">
          <div class="defect-issue-checkbox">
            <input type="checkbox"
                   id="issueCheck_${index}_${safeReportId}"
                   ${isSelected ? 'checked' : ''}
                   onchange="toggleIssueDefect('${index}', ${safeReportId}, this.checked)">
          </div>
          <div class="defect-issue-info">
            <span class="defect-issue-category">${escapeHtml(issue.issue_category_name || '부적합')}</span>
            <span class="defect-issue-item-name">${escapeHtml(itemText || '-')}</span>
            <span class="defect-issue-location">${escapeHtml(issue.workplace_name || issue.custom_location || '')}</span>
          </div>
          <div class="defect-issue-time ${isSelected ? 'active' : ''}">
            <div class="defect-time-input ${isSelected ? '' : 'disabled'}"
                 onclick="${isSelected ? `openIssueDefectTimePicker('${index}', ${safeReportId})` : ''}">
              <span class="defect-time-value" id="issueDefectTime_${index}_${safeReportId}">${parseFloat(defectHours) || 0}</span>
              <span class="defect-time-unit">시간</span>
            </div>
          </div>
        </div>
      `;
    });

    html += `
        </div>
      </div>
    `;

    // 레거시 방식도 추가 (기타 부적합 추가 버튼)
    html += `
      <div class="defect-legacy-section">
        <div class="defect-legacy-list" id="legacyDefectList_${index}">
          ${renderLegacyDefects(index, defects)}
        </div>
        <div class="defect-action-buttons">
          <button type="button" class="btn-add-defect-inline" onclick="addLegacyDefect('${index}')">
            + 부적합 추가
          </button>
          <button type="button" class="btn-save-defects" onclick="saveDefectsConfirm('${index}')" id="saveDefectsBtn_${index}">
            저장
          </button>
        </div>
        <div class="defect-save-message" id="defectSaveMessage_${index}" style="display: none;">
          <span class="save-message-text">부적합 내용이 저장되었습니다.</span>
        </div>
      </div>
    `;

    listContainer.innerHTML = html;
  } else {
    // 이슈가 없으면 레거시 UI (error_types 선택)
    const noIssueMsg = workerWorkplaceName
      ? `${escapeHtml(workerWorkplaceName)}에 신고된 부적합이 없습니다.`
      : '신고된 부적합이 없습니다.';
    listContainer.innerHTML = `
      <div class="defect-no-issues">
        <span class="no-issues-text">${noIssueMsg}</span>
      </div>
      <div class="defect-legacy-list" id="legacyDefectList_${index}">
        ${renderLegacyDefects(index, defects)}
      </div>
      <div class="defect-action-buttons">
        <button type="button" class="btn-add-defect-inline" onclick="addLegacyDefect('${index}')">
          + 부적합 추가
        </button>
        <button type="button" class="btn-save-defects" onclick="saveDefectsConfirm('${index}')" id="saveDefectsBtn_${index}">
          저장
        </button>
      </div>
      <div class="defect-save-message" id="defectSaveMessage_${index}" style="display: none;">
        <span class="save-message-text">부적합 내용이 저장되었습니다.</span>
      </div>
    `;
  }

  updateDefectSummary(index);
}

/**
 * 레거시 부적합 렌더링 (저장된 항목 + 입력 중인 항목 분리)
 */
function renderLegacyDefects(index, defects) {
  // issue_report_id가 없는 직접 입력 부적합
  const legacyDefects = defects.filter(d => !d.issue_report_id);

  if (legacyDefects.length === 0) return '';

  // 저장된 항목과 입력 중인 항목 분리
  const savedDefects = legacyDefects.filter(d => d._saved);
  const editingDefects = legacyDefects.filter(d => !d._saved);

  let html = '';

  // 저장된 부적합 표시 (위쪽)
  if (savedDefects.length > 0) {
    html += `<div class="defect-saved-section">
      <div class="defect-saved-header">
        <span class="defect-saved-title">저장된 부적합</span>
        <span class="defect-saved-count">${savedDefects.length}건</span>
      </div>
      <div class="defect-saved-list">`;

    savedDefects.forEach(defect => {
      const defectIndex = defects.indexOf(defect);
      const categoryName = defect.category_id
        ? (issueCategories.find(c => c.category_id == defect.category_id)?.category_name || '미분류')
        : '미분류';
      const itemName = defect.item_id
        ? (issueItems.find(i => i.item_id == defect.item_id)?.item_name || '')
        : '';

      const displayText = itemName
        ? `${categoryName} → ${itemName}`
        : categoryName;

      html += `
        <div class="defect-saved-item" data-defect-index="${defectIndex}">
          <div class="defect-saved-info">
            <span class="defect-saved-category">${categoryName}</span>
            <span class="defect-saved-detail">${itemName}${defect.note ? ' - ' + defect.note : ''}</span>
          </div>
          <div class="defect-saved-actions">
            <span class="defect-saved-hours">${defect.defect_hours || 0}시간</span>
            <button type="button" class="btn-edit-defect" onclick="editSavedDefect('${index}', ${defectIndex})">수정</button>
            <button type="button" class="btn-delete-defect" onclick="deleteSavedDefect('${index}', ${defectIndex})">삭제</button>
          </div>
        </div>
      `;
    });

    html += `</div></div>`;
  }

  // 입력 중인 부적합 표시 (아래쪽)
  if (editingDefects.length > 0) {
    html += `<div class="defect-editing-section">`;

    editingDefects.forEach(defect => {
      const defectIndex = defects.indexOf(defect);
      html += renderDefectInputForm(index, defect, defectIndex);
    });

    html += `</div>`;
  }

  return html;
}

/**
 * 부적합 입력 폼 렌더링 (단일 항목)
 */
function renderDefectInputForm(index, defect, defectIndex) {
  // 대분류 (카테고리) 옵션
  const categoryOptions = issueCategories.map(cat =>
    `<option value="${cat.category_id}" ${defect.category_id == cat.category_id ? 'selected' : ''}>${cat.category_name}</option>`
  ).join('');

  // 소분류 (아이템) 옵션 - 선택된 카테고리의 아이템만
  const filteredItems = defect.category_id
    ? issueItems.filter(item => item.category_id == defect.category_id)
    : [];
  const itemOptions = filteredItems.map(item =>
    `<option value="${item.item_id}" ${defect.item_id == item.item_id ? 'selected' : ''}>${item.item_name}</option>`
  ).join('');

  // 카테고리명/아이템명 표시 (미리보기용)
  const categoryName = defect.category_id
    ? (issueCategories.find(c => c.category_id == defect.category_id)?.category_name || '')
    : '';
  const itemName = defect.item_id
    ? (issueItems.find(i => i.item_id == defect.item_id)?.item_name || '')
    : '';

  return `
    <div class="defect-cascading-item" data-defect-index="${defectIndex}">
      <div class="defect-cascading-row">
        <!-- 대분류 (카테고리) -->
        <div class="defect-field">
          <label class="defect-field-label">대분류</label>
          <div class="defect-select-wrapper">
            <select class="defect-select defect-category-select"
                    id="defectCategory_${index}_${defectIndex}"
                    onchange="onDefectCategoryChange('${index}', ${defectIndex}, this.value)">
              <option value="">선택</option>
              ${categoryOptions}
              <option value="__new__">+ 새 대분류 추가</option>
            </select>
          </div>
        </div>

        <!-- 소분류 (아이템) -->
        <div class="defect-field">
          <label class="defect-field-label">소분류</label>
          <div class="defect-select-wrapper">
            <select class="defect-select defect-item-select"
                    id="defectItem_${index}_${defectIndex}"
                    onchange="onDefectItemChange('${index}', ${defectIndex}, this.value)"
                    ${!defect.category_id ? 'disabled' : ''}>
              <option value="">선택</option>
              ${itemOptions}
              ${defect.category_id ? '<option value="__new__">+ 새 소분류 추가</option>' : ''}
            </select>
          </div>
        </div>

        <!-- 시간 -->
        <div class="defect-field defect-field-time">
          <label class="defect-field-label">시간</label>
          <div class="defect-time-input"
               onclick="openDefectTimePicker('${index}', ${defectIndex})">
            <span class="defect-time-value" id="defectTime_${index}_${defectIndex}">${defect.defect_hours || 0}</span>
            <span class="defect-time-unit">시간</span>
          </div>
        </div>

        <!-- 취소 버튼 -->
        <button type="button" class="btn-remove-defect" onclick="cancelDefectEdit('${index}', ${defectIndex})">×</button>
      </div>

      <!-- 추가내용 입력 -->
      <div class="defect-note-row">
        <input type="text" class="defect-note-input"
               id="defectNote_${index}_${defectIndex}"
               placeholder="추가 설명 (선택사항)"
               value="${defect.note || ''}"
               onchange="updateInlineDefect('${index}', ${defectIndex}, 'note', this.value)">
      </div>

      <!-- 선택 미리보기 -->
      ${(categoryName || itemName) ? `
      <div class="defect-preview">
        <span class="defect-preview-text">
          ${categoryName}${itemName ? ' → ' + itemName : ''}${defect.note ? ' → ' + defect.note : ''}
        </span>
      </div>
      ` : ''}
    </div>
  `;
}

/**
 * 대분류 선택 변경
 */
window.onDefectCategoryChange = async function(index, defectIndex, value) {
  if (!tempDefects[index] || !tempDefects[index][defectIndex]) return;

  const defect = tempDefects[index][defectIndex];

  if (value === '__new__') {
    // 새 카테고리 추가 모달
    const newName = prompt('새 대분류(카테고리) 이름을 입력하세요:');
    if (newName && newName.trim()) {
      try {
        const response = await window.apiCall('/work-issues/categories', 'POST', {
          category_name: newName.trim(),
          category_type: 'nonconformity',
          severity: 'medium'
        });

        if (response.success) {
          // 카테고리 목록 새로고침
          await loadErrorTypes();
          // 새로 생성된 카테고리 선택
          const newCat = issueCategories.find(c => c.category_name === newName.trim());
          if (newCat) {
            defect.category_id = newCat.category_id;
            defect.item_id = null;
          }
        } else {
          alert('카테고리 추가 실패: ' + (response.error || '알 수 없는 오류'));
          defect.category_id = null;
        }
      } catch (e) {
        alert('카테고리 추가 중 오류: ' + e.message);
        defect.category_id = null;
      }
    } else {
      // 취소 시 이전 값 유지
      defect.category_id = defect.category_id || null;
    }
  } else if (value) {
    defect.category_id = parseInt(value);
    defect.item_id = null; // 카테고리 변경 시 소분류 초기화
  } else {
    defect.category_id = null;
    defect.item_id = null;
  }

  renderInlineDefectList(index);
  updateHiddenDefectFields(index);
};

/**
 * 소분류 선택 변경
 */
window.onDefectItemChange = async function(index, defectIndex, value) {
  if (!tempDefects[index] || !tempDefects[index][defectIndex]) return;

  const defect = tempDefects[index][defectIndex];

  if (value === '__new__') {
    // 새 아이템 추가 모달
    const newName = prompt('새 소분류(항목) 이름을 입력하세요:');
    if (newName && newName.trim() && defect.category_id) {
      try {
        const response = await window.apiCall('/work-issues/items', 'POST', {
          category_id: defect.category_id,
          item_name: newName.trim(),
          severity: 'medium'
        });

        if (response.success) {
          // 아이템 목록 새로고침
          await loadErrorTypes();
          // 새로 생성된 아이템 선택
          const newItem = issueItems.find(i => i.item_name === newName.trim() && i.category_id == defect.category_id);
          if (newItem) {
            defect.item_id = newItem.item_id;
          }
        } else {
          alert('항목 추가 실패: ' + (response.error || '알 수 없는 오류'));
        }
      } catch (e) {
        alert('항목 추가 중 오류: ' + e.message);
      }
    }
  } else if (value) {
    defect.item_id = parseInt(value);
  } else {
    defect.item_id = null;
  }

  renderInlineDefectList(index);
  updateHiddenDefectFields(index);
};

/**
 * 이슈 부적합 토글 (체크박스)
 */
window.toggleIssueDefect = function(index, issueReportId, isChecked) {
  if (!tempDefects[index]) {
    tempDefects[index] = [];
  }

  if (isChecked) {
    // 이슈 부적합 추가
    tempDefects[index].push({
      issue_report_id: issueReportId,
      error_type_id: null, // 이슈 기반이므로 null
      defect_hours: 0,
      note: ''
    });
  } else {
    // 이슈 부적합 제거
    const idx = tempDefects[index].findIndex(d => d.issue_report_id == issueReportId);
    if (idx !== -1) {
      tempDefects[index].splice(idx, 1);
    }
  }

  renderInlineDefectList(index);
  updateHiddenDefectFields(index);
};

/**
 * 이슈 부적합 시간 선택기 열기
 */
window.openIssueDefectTimePicker = function(index, issueReportId) {
  // 해당 이슈의 defect 찾기
  const defects = tempDefects[index] || [];
  const defectIndex = defects.findIndex(d => d.issue_report_id == issueReportId);

  if (defectIndex === -1) return;

  currentEditingField = { index, type: 'issueDefect', issueReportId, defectIndex };
  currentTimeValue = defects[defectIndex]?.defect_hours || 0;

  // 팝오버 표시
  const overlay = document.getElementById('timePickerOverlay');
  const title = document.getElementById('timePickerTitle');

  title.textContent = '부적합 시간 선택';
  updateTimeDisplay();

  overlay.style.display = 'flex';

  // ESC 키로 닫기
  document.addEventListener('keydown', handleEscapeKey);
};

/**
 * 레거시 부적합 추가 (error_types 기반)
 */
window.addLegacyDefect = function(index) {
  if (!tempDefects[index]) {
    tempDefects[index] = [];
  }

  tempDefects[index].push({
    issue_report_id: null,
    category_id: null,
    item_id: null,
    error_type_id: '', // 레거시 호환
    defect_hours: 0,
    note: ''
  });

  renderInlineDefectList(index);
};

/**
 * 부적합 카테고리/아이템 선택 업데이트 (레거시 호환)
 * @deprecated onDefectCategoryChange, onDefectItemChange 사용 권장
 */
window.updateDefectCategory = function(index, defectIndex, value) {
  // 레거시 호환 - 새 함수로 리다이렉트
  if (value && value.startsWith('cat_')) {
    onDefectCategoryChange(index, defectIndex, value.replace('cat_', ''));
  } else if (value && value.startsWith('item_')) {
    const itemId = parseInt(value.replace('item_', ''));
    const item = issueItems.find(i => i.item_id === itemId);
    if (item) {
      if (!tempDefects[index]?.[defectIndex]) return;
      tempDefects[index][defectIndex].category_id = item.category_id;
      tempDefects[index][defectIndex].item_id = itemId;
      renderInlineDefectList(index);
      updateHiddenDefectFields(index);
    }
  }
};

/**
 * 인라인 부적합 추가 (레거시 호환)
 */
window.addInlineDefect = function(index) {
  addLegacyDefect(index);
};

/**
 * 부적합 저장 확인 (유효성 검사 후 저장 상태로 변경)
 */
window.saveDefectsConfirm = function(index) {
  const defects = tempDefects[index] || [];
  // 입력 중인 항목만 (저장되지 않은 항목)
  const editingDefects = defects.filter(d => !d.issue_report_id && !d._saved);

  if (editingDefects.length === 0) {
    alert('저장할 부적합 항목이 없습니다.\n"+ 부적합 추가" 버튼을 눌러 항목을 추가하세요.');
    return;
  }

  // 유효성 검사
  const invalidDefects = [];
  editingDefects.forEach((defect, i) => {
    const errors = [];
    if (!defect.category_id) {
      errors.push('대분류');
    }
    if (!defect.defect_hours || defect.defect_hours <= 0) {
      errors.push('시간');
    }
    if (errors.length > 0) {
      invalidDefects.push({ index: i + 1, errors });
    }
  });

  if (invalidDefects.length > 0) {
    const errorMsg = invalidDefects.map(d =>
      `${d.index}번째 항목: ${d.errors.join(', ')} 미입력`
    ).join('\n');
    alert(`입력이 완료되지 않은 항목이 있습니다.\n\n${errorMsg}`);
    return;
  }

  // 모든 입력 중인 항목을 저장 상태로 변경
  editingDefects.forEach(defect => {
    defect._saved = true;
  });

  // UI 다시 렌더링
  renderInlineDefectList(index);
  updateHiddenDefectFields(index);
  updateDefectSummary(index);

  console.log(`[부적합 저장] index=${index}, 저장된 항목 수=${editingDefects.length}`);
};

/**
 * 저장된 부적합 수정 (저장 상태 해제하여 입력 폼으로 이동)
 */
window.editSavedDefect = function(index, defectIndex) {
  if (!tempDefects[index] || !tempDefects[index][defectIndex]) return;

  // 원래 저장 상태였음을 기록 (취소 시 복원용)
  tempDefects[index][defectIndex]._originalSaved = true;
  tempDefects[index][defectIndex]._saved = false;

  // UI 다시 렌더링
  renderInlineDefectList(index);
};

/**
 * 저장된 부적합 삭제
 */
window.deleteSavedDefect = function(index, defectIndex) {
  if (!tempDefects[index] || !tempDefects[index][defectIndex]) return;

  if (!confirm('이 부적합 항목을 삭제하시겠습니까?')) return;

  tempDefects[index].splice(defectIndex, 1);

  // UI 다시 렌더링
  renderInlineDefectList(index);
  updateHiddenDefectFields(index);
  updateDefectSummary(index);
};

/**
 * 부적합 입력 취소 (저장되지 않은 항목 삭제)
 */
window.cancelDefectEdit = function(index, defectIndex) {
  if (!tempDefects[index] || !tempDefects[index][defectIndex]) return;

  const defect = tempDefects[index][defectIndex];

  // 원래 저장된 항목이었으면 저장 상태로 복원, 아니면 삭제
  if (defect._originalSaved) {
    defect._saved = true;
    delete defect._originalSaved;
  } else {
    tempDefects[index].splice(defectIndex, 1);
  }

  // UI 다시 렌더링
  renderInlineDefectList(index);
  updateHiddenDefectFields(index);
  updateDefectSummary(index);
};

/**
 * 인라인 부적합 수정
 */
window.updateInlineDefect = function(index, defectIndex, field, value) {
  if (tempDefects[index] && tempDefects[index][defectIndex]) {
    if (field === 'defect_hours') {
      tempDefects[index][defectIndex][field] = parseFloat(value) || 0;
    } else {
      tempDefects[index][defectIndex][field] = value;
    }
    updateDefectSummary(index);
    updateHiddenDefectFields(index);
  }
};

/**
 * 인라인 부적합 삭제
 */
window.removeInlineDefect = function(index, defectIndex) {
  if (tempDefects[index]) {
    tempDefects[index].splice(defectIndex, 1);

    // UI 다시 렌더링 (항상 - 빈 상태도 표시)
    renderInlineDefectList(index);
    updateDefectSummary(index);
    updateHiddenDefectFields(index);
  }
};

/**
 * 부적합 시간 선택기 열기 (시간 선택 팝오버 재사용)
 */
window.openDefectTimePicker = function(index, defectIndex) {
  currentEditingField = { index, type: 'defect', defectIndex };

  // 현재 값 가져오기
  const defects = tempDefects[index] || [];
  currentTimeValue = defects[defectIndex]?.defect_hours || 0;

  // 팝오버 표시
  const overlay = document.getElementById('timePickerOverlay');
  const title = document.getElementById('timePickerTitle');

  title.textContent = '부적합 시간 선택';
  updateTimeDisplay();

  overlay.style.display = 'flex';

  // ESC 키로 닫기
  document.addEventListener('keydown', handleEscapeKey);
};

/**
 * hidden input 필드 업데이트
 */
function updateHiddenDefectFields(index) {
  const defects = tempDefects[index] || [];

  // 총 부적합 시간 계산
  const totalErrorHours = defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0);

  // hidden input에 대표 error_type_id 저장 (첫 번째 값, item_id fallback)
  const errorTypeInput = document.getElementById(`errorType_${index}`);
  const errorTypeId = defects.length > 0 ? (defects[0].error_type_id || defects[0].item_id || null) : null;
  if (errorTypeInput && errorTypeId) {
    errorTypeInput.value = errorTypeId;
  } else if (errorTypeInput) {
    errorTypeInput.value = '';
  }

  // 부적합 시간 input 업데이트
  const errorHoursInput = document.getElementById(`errorHours_${index}`);
  if (errorHoursInput) {
    errorHoursInput.value = totalErrorHours;
  }
}

/**
 * 부적합 요약 텍스트 업데이트
 * - 이슈 기반 부적합과 레거시 부적합 모두 포함
 */
function updateDefectSummary(index) {
  const summaryEl = document.getElementById(`defectSummary_${index}`);
  const toggleBtn = document.getElementById(`defectToggle_${index}`);
  if (!summaryEl) return;

  const defects = tempDefects[index] || [];
  // 이슈 기반 또는 레거시 부적합 중 시간이 입력된 것만 유효 (item_id도 체크)
  const validDefects = defects.filter(d => (d.issue_report_id || d.category_id || d.item_id || d.error_type_id) && d.defect_hours > 0);

  if (validDefects.length === 0) {
    summaryEl.textContent = '없음';
    summaryEl.style.color = '#6b7280';
    if (toggleBtn) toggleBtn.classList.remove('has-defect');
  } else {
    const totalHours = validDefects.reduce((sum, d) => sum + d.defect_hours, 0);
    if (validDefects.length === 1) {
      let typeName = '부적합';
      if (validDefects[0].issue_report_id) {
        // 이슈 기반 - 이슈 캐시에서 이름 찾기
        const tbm = incompleteTbms[index];
        if (tbm) {
          const dateStr = formatDateForApi(tbm.session_date);
          const issues = dailyIssuesCache[dateStr] || [];
          const issue = issues.find(i => i.report_id == validDefects[0].issue_report_id);
          typeName = issue?.issue_item_name || issue?.issue_category_name || '부적합';
        }
      } else if (validDefects[0].item_id) {
        // 신규 방식 - issue_report_items에서 이름 찾기
        typeName = issueItems.find(i => i.item_id == validDefects[0].item_id)?.item_name || '부적합';
      } else if (validDefects[0].category_id) {
        // 카테고리만 선택된 경우
        typeName = issueCategories.find(c => c.category_id == validDefects[0].category_id)?.category_name || '부적합';
      } else if (validDefects[0].error_type_id) {
        // 레거시 - error_types에서 이름 찾기 또는 issue_report_items에서 찾기
        typeName = issueItems.find(i => i.item_id == validDefects[0].error_type_id)?.item_name ||
                   errorTypes.find(et => et.id == validDefects[0].error_type_id)?.name || '부적합';
      }
      summaryEl.textContent = `${typeName} ${totalHours}h`;
    } else {
      summaryEl.textContent = `${validDefects.length}건 ${totalHours}h`;
    }
    summaryEl.style.color = '#dc2626';
    if (toggleBtn) toggleBtn.classList.add('has-defect');
  }

  // hidden 필드도 업데이트
  updateHiddenDefectFields(index);
}
