/**
 * 회의록 작성 및 공유 개선 서비스 - 공통 Javascript
 * @version 1.0
 * @author 최유진 (Frontend Developer)
 * @date 2025-10-20
 *
 * 이 파일은 모든 HTML 프로토타입에서 공통으로 사용되는 유틸리티 함수와
 * 상태 관리, 예제 데이터를 제공합니다.
 */

/* ============================================================================
   1. DOM 헬퍼 함수
   ============================================================================ */

/**
 * 단일 요소 선택 (querySelector 단축)
 * @param {string} selector - CSS 선택자
 * @returns {Element|null}
 */
const $ = (selector) => document.querySelector(selector);

/**
 * 복수 요소 선택 (querySelectorAll 단축)
 * @param {string} selector - CSS 선택자
 * @returns {NodeList}
 */
const $$ = (selector) => document.querySelectorAll(selector);

/**
 * 엘리먼트 생성 헬퍼
 * @param {string} tag - HTML 태그명
 * @param {string} className - CSS 클래스명 (선택)
 * @param {string} text - 텍스트 콘텐츠 (선택)
 * @returns {HTMLElement}
 */
function createElement(tag, className = '', text = '') {
  const element = document.createElement(tag);
  if (className) element.className = className;
  if (text) element.textContent = text;
  return element;
}

/**
 * 클래스 추가
 * @param {Element} element - 대상 엘리먼트
 * @param {string} className - 추가할 클래스명
 */
function addClass(element, className) {
  if (element) element.classList.add(className);
}

/**
 * 클래스 제거
 * @param {Element} element - 대상 엘리먼트
 * @param {string} className - 제거할 클래스명
 */
function removeClass(element, className) {
  if (element) element.classList.remove(className);
}

/**
 * 클래스 토글
 * @param {Element} element - 대상 엘리먼트
 * @param {string} className - 토글할 클래스명
 */
function toggleClass(element, className) {
  if (element) element.classList.toggle(className);
}

/* ============================================================================
   2. 화면 네비게이션 유틸리티
   ============================================================================ */

/**
 * 화면 이동 함수
 * @param {string} screenName - 이동할 화면 파일명 (예: '02-대시보드.html')
 */
function navigateTo(screenName) {
  // 파일 확장자가 없으면 .html 추가
  const fileName = screenName.includes('.html') ? screenName : `${screenName}.html`;

  // 현재 경로 저장 (뒤로가기 용)
  const currentPath = window.location.pathname;
  sessionStorage.setItem('previousScreen', currentPath);

  // 화면 전환 애니메이션 (선택)
  document.body.style.opacity = '0';
  setTimeout(() => {
    window.location.href = fileName;
  }, 150);
}

/**
 * 뒤로가기 함수
 */
function goBack() {
  const previousScreen = sessionStorage.getItem('previousScreen');

  if (previousScreen && previousScreen !== window.location.pathname) {
    navigateTo(previousScreen);
  } else {
    // 이전 화면이 없으면 대시보드로
    navigateTo('02-대시보드.html');
  }
}

/* ============================================================================
   3. 모달 관리
   ============================================================================ */

/**
 * 모달 표시
 * @param {string} id - 모달 엘리먼트 ID
 */
function showModal(id) {
  const modal = $(`#${id}`);
  if (!modal) {
    console.error(`Modal with id "${id}" not found`);
    return;
  }

  modal.style.display = 'flex';
  modal.setAttribute('aria-hidden', 'false');

  // 애니메이션
  setTimeout(() => {
    addClass(modal, 'modal-active');
  }, 10);

  // 배경 스크롤 방지
  document.body.style.overflow = 'hidden';

  // ESC 키로 닫기
  const handleEscape = (e) => {
    if (e.key === 'Escape') {
      hideModal(id);
      document.removeEventListener('keydown', handleEscape);
    }
  };
  document.addEventListener('keydown', handleEscape);

  // 포커스 트랩
  trapFocus(modal);
}

/**
 * 모달 숨기기
 * @param {string} id - 모달 엘리먼트 ID
 */
function hideModal(id) {
  const modal = $(`#${id}`);
  if (!modal) return;

  removeClass(modal, 'modal-active');

  setTimeout(() => {
    modal.style.display = 'none';
    modal.setAttribute('aria-hidden', 'true');
    document.body.style.overflow = '';
  }, 150);
}

/**
 * 모달 외부 클릭 시 닫기 설정
 * @param {string} id - 모달 엘리먼트 ID
 */
function setupModalClickOutside(id) {
  const modal = $(`#${id}`);
  if (!modal) return;

  modal.addEventListener('click', (e) => {
    if (e.target === modal) {
      hideModal(id);
    }
  });
}

/**
 * 포커스 트랩 (모달 내부에만 포커스 유지)
 * @param {Element} container - 포커스를 가둘 컨테이너
 */
function trapFocus(container) {
  const focusableElements = container.querySelectorAll(
    'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
  );
  const firstElement = focusableElements[0];
  const lastElement = focusableElements[focusableElements.length - 1];

  firstElement?.focus();

  container.addEventListener('keydown', (e) => {
    if (e.key !== 'Tab') return;

    if (e.shiftKey && document.activeElement === firstElement) {
      e.preventDefault();
      lastElement?.focus();
    } else if (!e.shiftKey && document.activeElement === lastElement) {
      e.preventDefault();
      firstElement?.focus();
    }
  });
}

/* ============================================================================
   4. Toast 알림
   ============================================================================ */

/**
 * 토스트 메시지 표시
 * @param {string} message - 표시할 메시지
 * @param {string} type - 타입 (success|error|info|warning)
 * @param {number} duration - 표시 시간 (ms, 기본 3000)
 */
function showToast(message, type = 'info', duration = 3000) {
  // 기존 토스트 제거
  const existingToast = $('.toast');
  if (existingToast) {
    existingToast.remove();
  }

  // 토스트 생성
  const toast = createElement('div', `toast toast-${type}`, message);
  toast.setAttribute('role', 'alert');
  toast.setAttribute('aria-live', 'polite');

  document.body.appendChild(toast);

  // 애니메이션
  setTimeout(() => {
    addClass(toast, 'toast-show');
  }, 10);

  // 자동 제거
  setTimeout(() => {
    removeClass(toast, 'toast-show');
    setTimeout(() => {
      toast.remove();
    }, 150);
  }, duration);
}

/* ============================================================================
   5. 폼 검증
   ============================================================================ */

/**
 * 이메일 형식 검증
 * @param {string} email - 검증할 이메일
 * @returns {boolean}
 */
function validateEmail(email) {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
}

/**
 * 필수 입력 검증
 * @param {string} value - 검증할 값
 * @returns {boolean}
 */
function validateRequired(value) {
  return value !== null && value !== undefined && value.trim() !== '';
}

/**
 * 폼 전체 검증
 * @param {HTMLFormElement} formElement - 검증할 폼 엘리먼트
 * @returns {boolean} - 모든 필드가 유효하면 true
 */
function validateForm(formElement) {
  if (!formElement) return false;

  let isValid = true;
  const inputs = formElement.querySelectorAll('input[required], textarea[required], select[required]');

  inputs.forEach(input => {
    const value = input.value;
    const errorMsg = input.parentElement.querySelector('.input-error-message');

    // 필수 입력 검증
    if (!validateRequired(value)) {
      isValid = false;
      addClass(input, 'error');

      if (errorMsg) {
        errorMsg.textContent = `${input.getAttribute('aria-label') || '이 항목'}을 입력해주세요`;
      }
    }
    // 이메일 검증
    else if (input.type === 'email' && !validateEmail(value)) {
      isValid = false;
      addClass(input, 'error');

      if (errorMsg) {
        errorMsg.textContent = '올바른 이메일을 입력해주세요';
      }
    }
    // 검증 통과
    else {
      removeClass(input, 'error');
      if (errorMsg) {
        errorMsg.textContent = '';
      }
    }
  });

  return isValid;
}

/**
 * 실시간 입력 검증 설정
 * @param {HTMLInputElement} input - 입력 필드
 */
function setupRealtimeValidation(input) {
  input.addEventListener('blur', () => {
    const value = input.value;
    const errorMsg = input.parentElement.querySelector('.input-error-message');

    if (input.hasAttribute('required') && !validateRequired(value)) {
      addClass(input, 'error');
      if (errorMsg) {
        errorMsg.textContent = `${input.getAttribute('aria-label') || '이 항목'}을 입력해주세요`;
      }
    } else if (input.type === 'email' && !validateEmail(value)) {
      addClass(input, 'error');
      if (errorMsg) {
        errorMsg.textContent = '올바른 이메일을 입력해주세요';
      }
    } else {
      removeClass(input, 'error');
      if (errorMsg) {
        errorMsg.textContent = '';
      }
    }
  });

  input.addEventListener('input', () => {
    removeClass(input, 'error');
  });
}

/* ============================================================================
   6. 로컬 스토리지 관리
   ============================================================================ */

/**
 * 데이터 저장
 * @param {string} key - 저장할 키
 * @param {any} value - 저장할 값
 */
function saveData(key, value) {
  try {
    const jsonValue = JSON.stringify(value);
    localStorage.setItem(key, jsonValue);
  } catch (error) {
    console.error('데이터 저장 실패:', error);
  }
}

/**
 * 데이터 로드
 * @param {string} key - 로드할 키
 * @returns {any} - 저장된 값 (없으면 null)
 */
function loadData(key) {
  try {
    const jsonValue = localStorage.getItem(key);
    return jsonValue ? JSON.parse(jsonValue) : null;
  } catch (error) {
    console.error('데이터 로드 실패:', error);
    return null;
  }
}

/**
 * 데이터 삭제
 * @param {string} key - 삭제할 키
 */
function removeData(key) {
  try {
    localStorage.removeItem(key);
  } catch (error) {
    console.error('데이터 삭제 실패:', error);
  }
}

/* ============================================================================
   7. 날짜/시간 유틸리티
   ============================================================================ */

/**
 * 날짜 포맷 (YYYY-MM-DD)
 * @param {Date|string} date - 포맷할 날짜
 * @returns {string}
 */
function formatDate(date) {
  const d = new Date(date);
  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

/**
 * 시간 포맷 (HH:MM)
 * @param {Date|string} time - 포맷할 시간
 * @returns {string}
 */
function formatTime(time) {
  const d = new Date(time);
  const hours = String(d.getHours()).padStart(2, '0');
  const minutes = String(d.getMinutes()).padStart(2, '0');
  return `${hours}:${minutes}`;
}

/**
 * 날짜/시간 포맷 (YYYY-MM-DD HH:MM)
 * @param {Date|string} datetime - 포맷할 날짜/시간
 * @returns {string}
 */
function formatDateTime(datetime) {
  return `${formatDate(datetime)} ${formatTime(datetime)}`;
}

/**
 * D-day 계산
 * @param {Date|string} targetDate - 목표 날짜
 * @returns {string} - 예: 'D-5', 'D-day', 'D+3'
 */
function getDDay(targetDate) {
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  const target = new Date(targetDate);
  target.setHours(0, 0, 0, 0);

  const diffTime = target - today;
  const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));

  if (diffDays === 0) return 'D-day';
  if (diffDays > 0) return `D-${diffDays}`;
  return `D+${Math.abs(diffDays)}`;
}

/**
 * 상대 시간 표시 (예: 5분 전, 2시간 전)
 * @param {Date|string} date - 날짜
 * @returns {string}
 */
function getRelativeTime(date) {
  const now = new Date();
  const past = new Date(date);
  const diffMs = now - past;
  const diffMins = Math.floor(diffMs / (1000 * 60));
  const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
  const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));

  if (diffMins < 1) return '방금 전';
  if (diffMins < 60) return `${diffMins}분 전`;
  if (diffHours < 24) return `${diffHours}시간 전`;
  if (diffDays < 7) return `${diffDays}일 전`;
  return formatDate(date);
}

/* ============================================================================
   8. 이벤트 처리
   ============================================================================ */

/**
 * 디바운싱 (연속된 이벤트를 지연 처리)
 * @param {Function} func - 실행할 함수
 * @param {number} delay - 지연 시간 (ms)
 * @returns {Function}
 */
function debounce(func, delay = 300) {
  let timeoutId;
  return function (...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

/**
 * 쓰로틀링 (일정 시간마다 한 번만 실행)
 * @param {Function} func - 실행할 함수
 * @param {number} limit - 제한 시간 (ms)
 * @returns {Function}
 */
function throttle(func, limit = 100) {
  let inThrottle;
  return function (...args) {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => {
        inThrottle = false;
      }, limit);
    }
  };
}

/* ============================================================================
   9. 애니메이션 헬퍼
   ============================================================================ */

/**
 * 페이드 인 애니메이션
 * @param {Element} element - 대상 엘리먼트
 * @param {number} duration - 지속 시간 (ms, 기본 150)
 */
function fadeIn(element, duration = 150) {
  if (!element) return;

  element.style.opacity = '0';
  element.style.display = 'block';

  let start = null;
  function animate(timestamp) {
    if (!start) start = timestamp;
    const progress = timestamp - start;

    element.style.opacity = Math.min(progress / duration, 1);

    if (progress < duration) {
      requestAnimationFrame(animate);
    }
  }

  requestAnimationFrame(animate);
}

/**
 * 페이드 아웃 애니메이션
 * @param {Element} element - 대상 엘리먼트
 * @param {number} duration - 지속 시간 (ms, 기본 150)
 */
function fadeOut(element, duration = 150) {
  if (!element) return;

  let start = null;
  function animate(timestamp) {
    if (!start) start = timestamp;
    const progress = timestamp - start;

    element.style.opacity = 1 - Math.min(progress / duration, 1);

    if (progress < duration) {
      requestAnimationFrame(animate);
    } else {
      element.style.display = 'none';
    }
  }

  requestAnimationFrame(animate);
}

/**
 * 슬라이드 업 애니메이션
 * @param {Element} element - 대상 엘리먼트
 * @param {number} duration - 지속 시간 (ms, 기본 200)
 */
function slideUp(element, duration = 200) {
  if (!element) return;

  const height = element.offsetHeight;
  element.style.overflow = 'hidden';
  element.style.transition = `height ${duration}ms ease-out`;
  element.style.height = `${height}px`;

  setTimeout(() => {
    element.style.height = '0';
  }, 10);

  setTimeout(() => {
    element.style.display = 'none';
    element.style.height = '';
    element.style.overflow = '';
    element.style.transition = '';
  }, duration);
}

/**
 * 슬라이드 다운 애니메이션
 * @param {Element} element - 대상 엘리먼트
 * @param {number} duration - 지속 시간 (ms, 기본 200)
 */
function slideDown(element, duration = 200) {
  if (!element) return;

  element.style.display = 'block';
  const height = element.offsetHeight;

  element.style.overflow = 'hidden';
  element.style.height = '0';
  element.style.transition = `height ${duration}ms ease-out`;

  setTimeout(() => {
    element.style.height = `${height}px`;
  }, 10);

  setTimeout(() => {
    element.style.height = '';
    element.style.overflow = '';
    element.style.transition = '';
  }, duration);
}

/* ============================================================================
   10. 회의록 예제 데이터
   ============================================================================ */

/**
 * 참석자 예제 데이터
 */
const mockUsers = [
  { id: 1, name: '김민준', email: 'minjun.kim@company.com', role: 'Product Owner', avatar: '👨‍💼' },
  { id: 2, name: '박서연', email: 'seoyeon.park@company.com', role: 'AI Specialist', avatar: '👩‍💻' },
  { id: 3, name: '이준호', email: 'junho.lee@company.com', role: 'Backend Developer', avatar: '👨‍💻' },
  { id: 4, name: '최유진', email: 'yujin.choi@company.com', role: 'Frontend Developer', avatar: '👩‍🎨' },
  { id: 5, name: '정도현', email: 'dohyun.jung@company.com', role: 'QA Engineer', avatar: '👨‍🔬' }
];

/**
 * 회의록 예제 데이터
 */
const mockMeetings = [
  {
    id: 1,
    title: '프로젝트 킥오프',
    date: '2025-10-20',
    time: '14:00',
    status: 'confirmed', // confirmed | in-progress | draft
    attendees: [1, 2, 3, 4, 5],
    location: '회의실 A',
    template: 'kickoff',
    progress: 100,
    sections: [
      {
        title: '참석자',
        content: '김민준 (주관자), 박서연, 이준호, 최유진, 정도현',
        verified: true,
        verifiedBy: 1,
        verifiedAt: '2025-10-20 14:45'
      },
      {
        title: '안건',
        content: '- 프로젝트 목표 정의\n- 일정 및 마일스톤\n- 역할 분담',
        verified: true
      },
      {
        title: '논의 내용',
        content: 'Q1까지 MVP 완성을 목표로 설정. React 프레임워크와 AWS 인프라 사용 결정.',
        verified: true
      },
      {
        title: '결정 사항',
        content: '- 개발 프레임워크: React\n- 배포 환경: AWS\n- 주간 회의: 매주 월요일 10시',
        verified: true
      }
    ],
    todos: [
      {
        id: 1,
        content: '요구사항 정의서 작성',
        assignee: 1,
        dueDate: '2025-10-25',
        priority: 'high',
        status: 'pending'
      },
      {
        id: 2,
        content: '기술 스택 상세 검토',
        assignee: 2,
        dueDate: '2025-10-27',
        priority: 'medium',
        status: 'pending'
      }
    ],
    keywords: ['MVP', 'React', 'AWS']
  },
  {
    id: 2,
    title: '주간 회의',
    date: '2025-10-19',
    time: '10:00',
    status: 'in-progress',
    attendees: [1, 2, 3, 4, 5],
    location: '온라인',
    template: 'weekly',
    progress: 60,
    sections: [
      {
        title: '참석자',
        content: '김민준, 박서연, 이준호, 최유진, 정도현',
        verified: true
      },
      {
        title: '주간 실적',
        content: '- UI 프로토타입 완성\n- API 설계 초안 작성',
        verified: false
      },
      {
        title: '주요 이슈',
        content: '데이터베이스 스키마 변경 필요',
        verified: false
      }
    ],
    todos: [
      {
        id: 3,
        content: 'DB 스키마 수정',
        assignee: 3,
        dueDate: '2025-10-22',
        priority: 'high',
        status: 'pending'
      }
    ],
    keywords: ['주간회의', 'UI', 'API']
  },
  {
    id: 3,
    title: '스프린트 계획 회의',
    date: '2025-10-18',
    time: '14:30',
    status: 'confirmed',
    attendees: [1, 2, 3, 4],
    location: '회의실 B',
    template: 'scrum',
    progress: 100,
    sections: [
      {
        title: '참석자',
        content: '김민준, 박서연, 이준호, 최유진',
        verified: true
      },
      {
        title: '어제 한 일',
        content: '각 팀원별 작업 진행 상황 공유',
        verified: true
      },
      {
        title: '오늘 할 일',
        content: '스프린트 목표 설정 및 작업 할당',
        verified: true
      }
    ],
    todos: [],
    keywords: ['스프린트', '계획']
  },
  {
    id: 4,
    title: '기술 검토 회의',
    date: '2025-10-17',
    time: '15:00',
    status: 'confirmed',
    attendees: [2, 3, 4],
    location: '온라인',
    template: 'general',
    progress: 100,
    sections: [
      {
        title: '참석자',
        content: '박서연, 이준호, 최유진',
        verified: true
      },
      {
        title: '논의 내용',
        content: 'AI 모델 선택 및 RAG 시스템 구조 검토',
        verified: true
      }
    ],
    todos: [
      {
        id: 4,
        content: 'AI 모델 벤치마크 테스트',
        assignee: 2,
        dueDate: '2025-10-24',
        priority: 'high',
        status: 'completed',
        completedAt: '2025-10-18'
      }
    ],
    keywords: ['AI', 'RAG', '기술검토']
  },
  {
    id: 5,
    title: '디자인 리뷰',
    date: '2025-10-16',
    time: '11:00',
    status: 'confirmed',
    attendees: [1, 4, 5],
    location: '회의실 C',
    template: 'general',
    progress: 100,
    sections: [
      {
        title: '참석자',
        content: '김민준, 최유진, 정도현',
        verified: true
      },
      {
        title: '논의 내용',
        content: 'UI/UX 설계 및 프로토타입 리뷰',
        verified: true
      },
      {
        title: '결정 사항',
        content: 'Mobile First 접근 방식 채택',
        verified: true
      }
    ],
    todos: [
      {
        id: 5,
        content: '프로토타입 수정',
        assignee: 4,
        dueDate: '2025-10-20',
        priority: 'medium',
        status: 'completed',
        completedAt: '2025-10-19'
      }
    ],
    keywords: ['디자인', 'UI', 'UX']
  }
];

/**
 * Todo 예제 데이터
 */
const mockTodos = [
  {
    id: 1,
    content: '요구사항 정의서 작성',
    assignee: 1,
    assigneeName: '김민준',
    dueDate: '2025-10-25',
    priority: 'high',
    status: 'pending',
    meetingId: 1,
    meetingTitle: '프로젝트 킥오프',
    meetingDate: '2025-10-20'
  },
  {
    id: 2,
    content: '기술 스택 상세 검토',
    assignee: 2,
    assigneeName: '박서연',
    dueDate: '2025-10-27',
    priority: 'medium',
    status: 'pending',
    meetingId: 1,
    meetingTitle: '프로젝트 킥오프',
    meetingDate: '2025-10-20'
  },
  {
    id: 3,
    content: 'DB 스키마 수정',
    assignee: 3,
    assigneeName: '이준호',
    dueDate: '2025-10-22',
    priority: 'high',
    status: 'pending',
    meetingId: 2,
    meetingTitle: '주간 회의',
    meetingDate: '2025-10-19'
  },
  {
    id: 4,
    content: 'AI 모델 벤치마크 테스트',
    assignee: 2,
    assigneeName: '박서연',
    dueDate: '2025-10-24',
    priority: 'high',
    status: 'completed',
    completedAt: '2025-10-18',
    meetingId: 4,
    meetingTitle: '기술 검토 회의',
    meetingDate: '2025-10-17'
  },
  {
    id: 5,
    content: '프로토타입 수정',
    assignee: 4,
    assigneeName: '최유진',
    dueDate: '2025-10-20',
    priority: 'medium',
    status: 'completed',
    completedAt: '2025-10-19',
    meetingId: 5,
    meetingTitle: '디자인 리뷰',
    meetingDate: '2025-10-16'
  }
];

/**
 * 사용자별 Todo 가져오기
 * @param {number} userId - 사용자 ID
 * @returns {Array}
 */
function getTodosByUser(userId) {
  return mockTodos.filter(todo => todo.assignee === userId);
}

/**
 * 회의별 Todo 가져오기
 * @param {number} meetingId - 회의 ID
 * @returns {Array}
 */
function getTodosByMeeting(meetingId) {
  return mockTodos.filter(todo => todo.meetingId === meetingId);
}

/**
 * 사용자 정보 가져오기
 * @param {number} userId - 사용자 ID
 * @returns {Object|null}
 */
function getUserById(userId) {
  return mockUsers.find(user => user.id === userId) || null;
}

/**
 * 회의록 정보 가져오기
 * @param {number} meetingId - 회의 ID
 * @returns {Object|null}
 */
function getMeetingById(meetingId) {
  return mockMeetings.find(meeting => meeting.id === meetingId) || null;
}

/* ============================================================================
   11. 초기화 함수
   ============================================================================ */

/**
 * 공통 이벤트 리스너 등록 및 초기화
 */
function initCommon() {
  // 페이지 로드 시 페이드인
  document.body.style.opacity = '1';

  // 뒤로가기 버튼 이벤트
  const backButtons = $$('[data-action="back"]');
  backButtons.forEach(btn => {
    btn.addEventListener('click', goBack);
  });

  // 모달 외부 클릭 이벤트
  const modals = $$('.modal-overlay');
  modals.forEach(modal => {
    setupModalClickOutside(modal.id);
  });

  // 모달 닫기 버튼
  const closeButtons = $$('.modal-close');
  closeButtons.forEach(btn => {
    btn.addEventListener('click', (e) => {
      const modal = e.target.closest('.modal-overlay');
      if (modal) {
        hideModal(modal.id);
      }
    });
  });

  // 폼 실시간 검증
  const inputs = $$('input[required], input[type="email"]');
  inputs.forEach(input => {
    setupRealtimeValidation(input);
  });

  // 네비게이션 링크 활성화 표시
  highlightCurrentPage();

  // 로컬 스토리지 초기화 (첫 방문 시)
  initLocalStorage();

  console.log('Common.js initialized');
}

/**
 * 현재 페이지 네비게이션 하이라이트
 */
function highlightCurrentPage() {
  const currentPath = window.location.pathname;
  const navLinks = $$('[data-nav-link]');

  navLinks.forEach(link => {
    const href = link.getAttribute('href');
    if (currentPath.includes(href)) {
      addClass(link, 'active');
    }
  });
}

/**
 * 로컬 스토리지 초기화 (첫 방문 시)
 */
function initLocalStorage() {
  if (!loadData('initialized')) {
    // 현재 사용자 설정 (예제: 김민준)
    saveData('currentUser', { id: 1, name: '김민준', email: 'minjun.kim@company.com' });

    // 회의록 데이터
    saveData('meetings', mockMeetings);

    // Todo 데이터
    saveData('todos', mockTodos);

    // 초기화 완료 플래그
    saveData('initialized', true);

    console.log('Local storage initialized with mock data');
  }
}

/**
 * 현재 로그인 사용자 가져오기
 * @returns {Object|null}
 */
function getCurrentUser() {
  return loadData('currentUser');
}

/* ============================================================================
   12. DOM 로드 완료 시 초기화
   ============================================================================ */

// DOM 로드 완료 시 공통 초기화 실행
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', initCommon);
} else {
  initCommon();
}

/* ============================================================================
   전역 스코프에 함수 노출 (HTML에서 직접 호출 가능)
   ============================================================================ */

window.commonUtils = {
  // DOM
  $,
  $$,
  createElement,
  addClass,
  removeClass,
  toggleClass,

  // Navigation
  navigateTo,
  goBack,

  // Modal
  showModal,
  hideModal,
  setupModalClickOutside,

  // Toast
  showToast,

  // Validation
  validateEmail,
  validateRequired,
  validateForm,
  setupRealtimeValidation,

  // Storage
  saveData,
  loadData,
  removeData,

  // Date/Time
  formatDate,
  formatTime,
  formatDateTime,
  getDDay,
  getRelativeTime,

  // Events
  debounce,
  throttle,

  // Animation
  fadeIn,
  fadeOut,
  slideUp,
  slideDown,

  // Mock Data
  mockUsers,
  mockMeetings,
  mockTodos,
  getTodosByUser,
  getTodosByMeeting,
  getUserById,
  getMeetingById,
  getCurrentUser,

  // Init
  initCommon
};
