/**
 * vacation-allocation.js
 * 휴가 발생 입력 페이지 로직
 */

import { API_BASE_URL } from './api-config.js';

// 전역 변수
let workers = [];
let vacationTypes = [];
let currentWorkerBalances = [];

/**
 * 페이지 초기화
 */
document.addEventListener('DOMContentLoaded', async () => {
  // 관리자 권한 체크
  const user = JSON.parse(localStorage.getItem('sso_user') || '{}');
  console.log('Current user:', user);
  console.log('Role ID:', user.role_id, 'Role:', user.role);

  // role이 'Admin'이거나 role_id가 1 또는 2인 경우 허용
  const isAdmin = user.role === 'Admin' || [1, 2].includes(user.role_id);

  if (!isAdmin) {
    console.error('Access denied. User:', user);
    alert('관리자만 접근할 수 있습니다');
    window.location.href = '/pages/dashboard.html';
    return;
  }

  await loadInitialData();
  initializeYearSelectors();
  initializeTabNavigation();
  initializeEventListeners();
});

/**
 * 초기 데이터 로드
 */
async function loadInitialData() {
  await Promise.all([
    loadWorkers(),
    loadVacationTypes()
  ]);
}

/**
 * 작업자 목록 로드
 */
async function loadWorkers() {
  try {
    const token = localStorage.getItem('sso_token');
    console.log('Loading workers... Token:', token ? 'exists' : 'missing');

    const response = await fetch(`${API_BASE_URL}/api/workers`, {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    });

    console.log('Workers API Response status:', response.status);

    if (!response.ok) {
      const errorData = await response.json();
      console.error('Workers API Error:', errorData);
      throw new Error(errorData.message || '작업자 목록 로드 실패');
    }

    const result = await response.json();
    console.log('Workers data:', result);
    workers = result.data || [];

    if (workers.length === 0) {
      console.warn('No workers found in database');
      showToast('등록된 작업자가 없습니다', 'warning');
      return;
    }

    // 개별 입력 탭 - 작업자 셀렉트 박스 (부서별 그룹)
    const selectWorker = document.getElementById('individualWorker');
    const byDept = {};
    workers.forEach(worker => {
      const dept = worker.department_name || '부서 미지정';
      if (!byDept[dept]) byDept[dept] = [];
      byDept[dept].push(worker);
    });

    Object.keys(byDept).sort().forEach(dept => {
      const group = document.createElement('optgroup');
      group.label = dept;
      byDept[dept].forEach(worker => {
        const option = document.createElement('option');
        option.value = worker.user_id;
        option.textContent = `${worker.worker_name} (${worker.employment_status === 'employed' ? '재직' : '퇴사'})`;
        group.appendChild(option);
      });
      selectWorker.appendChild(group);
    });
    console.log(`Loaded ${workers.length} workers successfully`);
  } catch (error) {
    console.error('작업자 로드 오류:', error);
    showToast(`작업자 목록을 불러오는데 실패했습니다: ${error.message}`, 'error');
  }
}

/**
 * 휴가 유형 목록 로드
 */
async function loadVacationTypes() {
  try {
    const token = localStorage.getItem('sso_token');
    const response = await fetch(`${API_BASE_URL}/api/vacation-types`, {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    });

    if (!response.ok) throw new Error('휴가 유형 로드 실패');

    const result = await response.json();
    vacationTypes = result.data || [];

    // 개별 입력 탭 - 휴가 유형 셀렉트 박스
    const selectType = document.getElementById('individualVacationType');
    vacationTypes.forEach(type => {
      const option = document.createElement('option');
      option.value = type.id;
      option.textContent = `${type.type_name} ${type.is_special ? '(특별)' : ''}`;
      selectType.appendChild(option);
    });

    // 특별 휴가 관리 탭 테이블 로드
    loadSpecialTypesTable();
  } catch (error) {
    console.error('휴가 유형 로드 오류:', error);
    showToast('휴가 유형을 불러오는데 실패했습니다', 'error');
  }
}

/**
 * 연도 셀렉터 초기화
 */
function initializeYearSelectors() {
  const currentYear = new Date().getFullYear();
  const yearSelectors = ['individualYear', 'bulkYear'];

  yearSelectors.forEach(selectorId => {
    const select = document.getElementById(selectorId);
    for (let year = currentYear - 1; year <= currentYear + 2; year++) {
      const option = document.createElement('option');
      option.value = year;
      option.textContent = `${year}년`;
      if (year === currentYear) {
        option.selected = true;
      }
      select.appendChild(option);
    }
  });
}

/**
 * 탭 네비게이션 초기화
 */
function initializeTabNavigation() {
  const tabButtons = document.querySelectorAll('.tab-button');
  tabButtons.forEach(button => {
    button.addEventListener('click', () => {
      const tabName = button.dataset.tab;
      switchTab(tabName);
    });
  });
}

/**
 * 탭 전환
 */
function switchTab(tabName) {
  // 탭 버튼 활성화
  document.querySelectorAll('.tab-button').forEach(btn => {
    btn.classList.remove('active');
  });
  document.querySelector(`[data-tab="${tabName}"]`).classList.add('active');

  // 탭 콘텐츠 표시
  document.querySelectorAll('.tab-content').forEach(content => {
    content.classList.remove('active');
  });
  document.getElementById(`tab-${tabName}`).classList.add('active');
}

/**
 * 이벤트 리스너 초기화
 */
function initializeEventListeners() {
  // === 탭 1: 개별 입력 ===
  document.getElementById('individualWorker').addEventListener('change', loadWorkerBalances);
  document.getElementById('autoCalculateBtn').addEventListener('click', autoCalculateAnnualLeave);
  document.getElementById('individualSubmitBtn').addEventListener('click', submitIndividualVacation);
  document.getElementById('individualResetBtn').addEventListener('click', resetIndividualForm);

  // === 탭 2: 일괄 입력 ===
  document.getElementById('bulkPreviewBtn').addEventListener('click', previewBulkAllocation);
  document.getElementById('bulkSubmitBtn').addEventListener('click', submitBulkAllocation);

  // === 탭 3: 특별 휴가 관리 ===
  document.getElementById('addSpecialTypeBtn').addEventListener('click', () => openVacationTypeModal());

  // 모달 닫기
  document.querySelectorAll('.modal-close').forEach(btn => {
    btn.addEventListener('click', closeModals);
  });

  // 모달 폼 제출
  document.getElementById('vacationTypeForm').addEventListener('submit', submitVacationType);
  document.getElementById('editBalanceForm').addEventListener('submit', submitEditBalance);
}

// =============================================================================
// 탭 1: 개별 입력
// =============================================================================

/**
 * 작업자의 기존 휴가 잔액 로드
 */
async function loadWorkerBalances() {
  const workerId = document.getElementById('individualWorker').value;
  const year = document.getElementById('individualYear').value;

  if (!workerId) {
    document.getElementById('individualTableBody').innerHTML = `
      <tr><td colspan="8" class="loading-state"><p>작업자를 선택하세요</p></td></tr>
    `;
    return;
  }

  try {
    const token = localStorage.getItem('sso_token');
    const response = await fetch(`${API_BASE_URL}/api/vacation-balances/worker/${workerId}/year/${year}`, {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    });

    if (!response.ok) throw new Error('휴가 잔액 로드 실패');

    const result = await response.json();
    currentWorkerBalances = result.data || [];

    updateWorkerBalancesTable();
  } catch (error) {
    console.error('휴가 잔액 로드 오류:', error);
    showToast('휴가 잔액을 불러오는데 실패했습니다', 'error');
  }
}

/**
 * 작업자 휴가 잔액 테이블 업데이트
 */
function updateWorkerBalancesTable() {
  const tbody = document.getElementById('individualTableBody');

  if (currentWorkerBalances.length === 0) {
    tbody.innerHTML = `
      <tr><td colspan="8" class="loading-state"><p>등록된 휴가가 없습니다</p></td></tr>
    `;
    return;
  }

  tbody.innerHTML = currentWorkerBalances.map(balance => `
    <tr>
      <td>${balance.worker_name || '-'}</td>
      <td>${balance.year}</td>
      <td>${balance.type_name} ${balance.is_special ? '<span class="badge badge-info">특별</span>' : ''}</td>
      <td>${balance.total_days}일</td>
      <td>${balance.used_days}일</td>
      <td>${balance.remaining_days}일</td>
      <td>${balance.notes || '-'}</td>
      <td class="action-buttons">
        <button class="btn btn-sm btn-secondary btn-icon" onclick="window.editBalance(${balance.id})">✏️</button>
        <button class="btn btn-sm btn-danger btn-icon" onclick="window.deleteBalance(${balance.id})">🗑️</button>
      </td>
    </tr>
  `).join('');
}

/**
 * 자동 계산 (연차만 해당)
 */
async function autoCalculateAnnualLeave() {
  const workerId = document.getElementById('individualWorker').value;
  const year = document.getElementById('individualYear').value;
  const typeId = document.getElementById('individualVacationType').value;

  if (!workerId) {
    showToast('작업자를 선택하세요', 'warning');
    return;
  }

  // 선택한 휴가 유형이 ANNUAL인지 확인
  const selectedType = vacationTypes.find(t => t.id == typeId);
  if (!selectedType || selectedType.type_code !== 'ANNUAL') {
    showToast('연차(ANNUAL) 유형만 자동 계산이 가능합니다', 'warning');
    return;
  }

  // 작업자의 입사일 조회
  const worker = workers.find(w => w.user_id == workerId);
  if (!worker || !worker.hire_date) {
    showToast('작업자의 입사일 정보가 없습니다', 'error');
    return;
  }

  try {
    const token = localStorage.getItem('sso_token');
    const response = await fetch(`${API_BASE_URL}/api/vacation-balances/auto-calculate`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        user_id: workerId,
        hire_date: worker.hire_date,
        year: year
      })
    });

    const result = await response.json();

    if (!response.ok) {
      throw new Error(result.message || '자동 계산 실패');
    }

    // 계산 결과 표시
    const resultDiv = document.getElementById('autoCalculateResult');
    resultDiv.innerHTML = `
      <strong>자동 계산 완료</strong><br>
      입사일: ${worker.hire_date}<br>
      계산된 연차: ${result.data.calculated_days}일<br>
      아래 "총 부여 일수"에 자동으로 입력됩니다.
    `;
    resultDiv.style.display = 'block';

    // 폼에 자동 입력
    document.getElementById('individualTotalDays').value = result.data.calculated_days;
    document.getElementById('individualNotes').value = `근속년수 기반 자동 계산 (입사일: ${worker.hire_date})`;

    showToast(result.message, 'success');

    // 기존 데이터 새로고침
    await loadWorkerBalances();
  } catch (error) {
    console.error('자동 계산 오류:', error);
    showToast(error.message, 'error');
  }
}

/**
 * 개별 휴가 제출
 */
async function submitIndividualVacation() {
  const workerId = document.getElementById('individualWorker').value;
  const year = document.getElementById('individualYear').value;
  const typeId = document.getElementById('individualVacationType').value;
  const totalDays = document.getElementById('individualTotalDays').value;
  const usedDays = document.getElementById('individualUsedDays').value || 0;
  const notes = document.getElementById('individualNotes').value;

  if (!workerId || !year || !typeId || !totalDays) {
    showToast('필수 항목을 모두 입력하세요', 'warning');
    return;
  }

  try {
    const token = localStorage.getItem('sso_token');
    const response = await fetch(`${API_BASE_URL}/api/vacation-balances`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        user_id: workerId,
        vacation_type_id: typeId,
        year: year,
        total_days: parseFloat(totalDays),
        used_days: parseFloat(usedDays),
        notes: notes
      })
    });

    const result = await response.json();

    if (!response.ok) {
      throw new Error(result.message || '저장 실패');
    }

    showToast('휴가가 등록되었습니다', 'success');
    resetIndividualForm();
    await loadWorkerBalances();
  } catch (error) {
    console.error('휴가 등록 오류:', error);
    showToast(error.message, 'error');
  }
}

/**
 * 개별 입력 폼 초기화
 */
function resetIndividualForm() {
  document.getElementById('individualVacationType').value = '';
  document.getElementById('individualTotalDays').value = '';
  document.getElementById('individualUsedDays').value = '0';
  document.getElementById('individualNotes').value = '';
  document.getElementById('autoCalculateResult').style.display = 'none';
}

/**
 * 휴가 수정 (전역 함수로 노출)
 */
window.editBalance = function(balanceId) {
  const balance = currentWorkerBalances.find(b => b.id === balanceId);
  if (!balance) return;

  document.getElementById('editBalanceId').value = balance.id;
  document.getElementById('editTotalDays').value = balance.total_days;
  document.getElementById('editUsedDays').value = balance.used_days;
  document.getElementById('editNotes').value = balance.notes || '';

  document.getElementById('editBalanceModal').classList.add('active');
};

/**
 * 휴가 삭제 (전역 함수로 노출)
 */
window.deleteBalance = async function(balanceId) {
  if (!confirm('정말 삭제하시겠습니까?')) return;

  try {
    const token = localStorage.getItem('sso_token');
    const response = await fetch(`${API_BASE_URL}/api/vacation-balances/${balanceId}`, {
      method: 'DELETE',
      headers: {
        'Authorization': `Bearer ${token}`
      }
    });

    const result = await response.json();

    if (!response.ok) {
      throw new Error(result.message || '삭제 실패');
    }

    showToast('삭제되었습니다', 'success');
    await loadWorkerBalances();
  } catch (error) {
    console.error('삭제 오류:', error);
    showToast(error.message, 'error');
  }
};

/**
 * 휴가 수정 제출
 */
async function submitEditBalance(e) {
  e.preventDefault();

  const balanceId = document.getElementById('editBalanceId').value;
  const totalDays = document.getElementById('editTotalDays').value;
  const usedDays = document.getElementById('editUsedDays').value;
  const notes = document.getElementById('editNotes').value;

  try {
    const token = localStorage.getItem('sso_token');
    const response = await fetch(`${API_BASE_URL}/api/vacation-balances/${balanceId}`, {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        total_days: parseFloat(totalDays),
        used_days: parseFloat(usedDays),
        notes: notes
      })
    });

    const result = await response.json();

    if (!response.ok) {
      throw new Error(result.message || '수정 실패');
    }

    showToast('수정되었습니다', 'success');
    closeModals();
    await loadWorkerBalances();
  } catch (error) {
    console.error('수정 오류:', error);
    showToast(error.message, 'error');
  }
}

// =============================================================================
// 탭 2: 일괄 입력
// =============================================================================

let bulkPreviewData = [];

/**
 * 일괄 할당 미리보기
 */
async function previewBulkAllocation() {
  const year = document.getElementById('bulkYear').value;
  const employmentStatus = document.getElementById('bulkEmploymentStatus').value;

  // 필터링된 작업자 목록
  let targetWorkers = workers;
  if (employmentStatus === 'employed') {
    targetWorkers = workers.filter(w => w.employment_status === 'employed');
  }

  // ANNUAL 유형 찾기
  const annualType = vacationTypes.find(t => t.type_code === 'ANNUAL');
  if (!annualType) {
    showToast('ANNUAL 휴가 유형이 없습니다', 'error');
    return;
  }

  // 미리보기 데이터 생성
  bulkPreviewData = targetWorkers.map(worker => {
    const hireDate = worker.hire_date;
    if (!hireDate) {
      return {
        user_id: worker.user_id,
        worker_name: worker.worker_name,
        hire_date: '-',
        years_worked: '-',
        calculated_days: 0,
        reason: '입사일 정보 없음',
        status: 'error'
      };
    }

    const calculatedDays = calculateAnnualLeaveDays(hireDate, year);
    const yearsWorked = calculateYearsWorked(hireDate, year);

    return {
      user_id: worker.user_id,
      worker_name: worker.worker_name,
      hire_date: hireDate,
      years_worked: yearsWorked,
      calculated_days: calculatedDays,
      reason: getCalculationReason(yearsWorked, calculatedDays),
      status: 'ready'
    };
  });

  updateBulkPreviewTable();
  document.getElementById('bulkPreviewSection').style.display = 'block';
  document.getElementById('bulkSubmitBtn').disabled = false;
}

/**
 * 연차 일수 계산 (한국 근로기준법)
 */
function calculateAnnualLeaveDays(hireDate, targetYear) {
  const hire = new Date(hireDate);
  const targetDate = new Date(targetYear, 0, 1);

  const monthsDiff = (targetDate.getFullYear() - hire.getFullYear()) * 12
                   + (targetDate.getMonth() - hire.getMonth());

  // 1년 미만: 월 1일
  if (monthsDiff < 12) {
    return Math.floor(monthsDiff);
  }

  // 1년 이상: 15일 기본 + 2년마다 1일 추가 (최대 25일)
  const yearsWorked = Math.floor(monthsDiff / 12);
  const additionalDays = Math.floor((yearsWorked - 1) / 2);

  return Math.min(15 + additionalDays, 25);
}

/**
 * 근속년수 계산
 */
function calculateYearsWorked(hireDate, targetYear) {
  const hire = new Date(hireDate);
  const targetDate = new Date(targetYear, 0, 1);

  const monthsDiff = (targetDate.getFullYear() - hire.getFullYear()) * 12
                   + (targetDate.getMonth() - hire.getMonth());

  return (monthsDiff / 12).toFixed(1);
}

/**
 * 계산 근거 생성
 */
function getCalculationReason(yearsWorked, days) {
  const years = parseFloat(yearsWorked);
  if (years < 1) {
    return `입사 ${Math.floor(years * 12)}개월 (월 1일)`;
  }
  if (days === 25) {
    return '최대 25일 (근속 3년 이상)';
  }
  return `근속 ${Math.floor(years)}년 (15일 + ${days - 15}일)`;
}

/**
 * 일괄 미리보기 테이블 업데이트
 */
function updateBulkPreviewTable() {
  const tbody = document.getElementById('bulkPreviewTableBody');

  tbody.innerHTML = bulkPreviewData.map(item => {
    const statusBadge = item.status === 'error'
      ? '<span class="badge badge-error">오류</span>'
      : '<span class="badge badge-success">준비</span>';

    return `
      <tr>
        <td>${item.worker_name}</td>
        <td>${item.hire_date}</td>
        <td>${item.years_worked}년</td>
        <td>${item.calculated_days}일</td>
        <td>${item.reason}</td>
        <td>${statusBadge}</td>
      </tr>
    `;
  }).join('');
}

/**
 * 일괄 할당 제출
 */
async function submitBulkAllocation() {
  const year = document.getElementById('bulkYear').value;

  // 오류가 없는 항목만 필터링
  const validItems = bulkPreviewData.filter(item => item.status !== 'error' && item.calculated_days > 0);

  if (validItems.length === 0) {
    showToast('생성할 항목이 없습니다', 'warning');
    return;
  }

  if (!confirm(`${validItems.length}명의 연차를 생성하시겠습니까?`)) {
    return;
  }

  // ANNUAL 유형 찾기
  const annualType = vacationTypes.find(t => t.type_code === 'ANNUAL');

  let successCount = 0;
  let failCount = 0;

  for (const item of validItems) {
    try {
      const token = localStorage.getItem('sso_token');
      const response = await fetch(`${API_BASE_URL}/api/vacation-balances/auto-calculate`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          user_id: item.user_id,
          hire_date: item.hire_date,
          year: year
        })
      });

      if (response.ok) {
        successCount++;
      } else {
        failCount++;
      }
    } catch (error) {
      failCount++;
    }
  }

  showToast(`완료: ${successCount}건 성공, ${failCount}건 실패`, successCount > 0 ? 'success' : 'error');

  // 미리보기 초기화
  document.getElementById('bulkPreviewSection').style.display = 'none';
  document.getElementById('bulkSubmitBtn').disabled = true;
  bulkPreviewData = [];
}

// =============================================================================
// 탭 3: 특별 휴가 관리
// =============================================================================

/**
 * 특별 휴가 유형 테이블 로드
 */
function loadSpecialTypesTable() {
  const tbody = document.getElementById('specialTypesTableBody');

  if (vacationTypes.length === 0) {
    tbody.innerHTML = `
      <tr><td colspan="7" class="loading-state"><p>등록된 휴가 유형이 없습니다</p></td></tr>
    `;
    return;
  }

  tbody.innerHTML = vacationTypes.map(type => `
    <tr>
      <td>${type.type_name}</td>
      <td>${type.type_code}</td>
      <td>${type.priority}</td>
      <td>${type.is_special ? '<span class="badge badge-info">특별</span>' : '-'}</td>
      <td>${type.is_system ? '<span class="badge badge-warning">시스템</span>' : '-'}</td>
      <td>${type.description || '-'}</td>
      <td class="action-buttons">
        <button class="btn btn-sm btn-secondary btn-icon" onclick="window.editVacationType(${type.id})" ${type.is_system ? 'disabled' : ''}>✏️</button>
        <button class="btn btn-sm btn-danger btn-icon" onclick="window.deleteVacationType(${type.id})" ${type.is_system ? 'disabled' : ''}>🗑️</button>
      </td>
    </tr>
  `).join('');
}

/**
 * 휴가 유형 모달 열기
 */
function openVacationTypeModal(typeId = null) {
  const modal = document.getElementById('vacationTypeModal');
  const form = document.getElementById('vacationTypeForm');
  form.reset();

  if (typeId) {
    const type = vacationTypes.find(t => t.id === typeId);
    if (!type) return;

    document.getElementById('modalTitle').textContent = '휴가 유형 수정';
    document.getElementById('modalTypeId').value = type.id;
    document.getElementById('modalTypeName').value = type.type_name;
    document.getElementById('modalTypeCode').value = type.type_code;
    document.getElementById('modalPriority').value = type.priority;
    document.getElementById('modalIsSpecial').checked = type.is_special === 1;
    document.getElementById('modalDescription').value = type.description || '';
  } else {
    document.getElementById('modalTitle').textContent = '휴가 유형 추가';
    document.getElementById('modalTypeId').value = '';
  }

  modal.classList.add('active');
}

/**
 * 휴가 유형 수정 (전역 함수)
 */
window.editVacationType = function(typeId) {
  openVacationTypeModal(typeId);
};

/**
 * 휴가 유형 삭제 (전역 함수)
 */
window.deleteVacationType = async function(typeId) {
  if (!confirm('정말 삭제하시겠습니까?')) return;

  try {
    const token = localStorage.getItem('sso_token');
    const response = await fetch(`${API_BASE_URL}/api/vacation-types/${typeId}`, {
      method: 'DELETE',
      headers: {
        'Authorization': `Bearer ${token}`
      }
    });

    const result = await response.json();

    if (!response.ok) {
      throw new Error(result.message || '삭제 실패');
    }

    showToast('삭제되었습니다', 'success');
    await loadVacationTypes();
  } catch (error) {
    console.error('삭제 오류:', error);
    showToast(error.message, 'error');
  }
};

/**
 * 휴가 유형 제출
 */
async function submitVacationType(e) {
  e.preventDefault();

  const typeId = document.getElementById('modalTypeId').value;
  const typeName = document.getElementById('modalTypeName').value;
  const typeCode = document.getElementById('modalTypeCode').value;
  const priority = document.getElementById('modalPriority').value;
  const isSpecial = document.getElementById('modalIsSpecial').checked ? 1 : 0;
  const description = document.getElementById('modalDescription').value;

  const data = {
    type_name: typeName,
    type_code: typeCode.toUpperCase(),
    priority: parseInt(priority),
    is_special: isSpecial,
    description: description
  };

  try {
    const token = localStorage.getItem('sso_token');
    const url = typeId
      ? `${API_BASE_URL}/api/vacation-types/${typeId}`
      : `${API_BASE_URL}/api/vacation-types`;

    const response = await fetch(url, {
      method: typeId ? 'PUT' : 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    });

    const result = await response.json();

    if (!response.ok) {
      throw new Error(result.message || '저장 실패');
    }

    showToast(typeId ? '수정되었습니다' : '추가되었습니다', 'success');
    closeModals();
    await loadVacationTypes();
  } catch (error) {
    console.error('저장 오류:', error);
    showToast(error.message, 'error');
  }
}

// =============================================================================
// 공통 함수
// =============================================================================

/**
 * 모달 닫기
 */
function closeModals() {
  document.querySelectorAll('.modal').forEach(modal => {
    modal.classList.remove('active');
  });
}

// showToast → api-base.js 전역 사용
