
import { format, parse, isValid, parseISO } from 'date-fns';
import { ko } from 'date-fns/locale';

// 날짜 파싱 결과를 캐싱하기 위한 Map
const dateParseCache = new Map<string, Date | null>();

/**
 * 다양한 형식의 날짜 문자열을 Date 객체로 변환하는 유틸리티
 * 성능 최적화를 위해 결과 캐싱 기능 추가
 */
export const parseTransactionDate = (dateStr: string): Date | null => {
  // 빈 문자열 체크
  if (!dateStr || dateStr === '') {
    return null;
  }
  
  // 캐시된 결과가 있으면 반환
  if (dateParseCache.has(dateStr)) {
    return dateParseCache.get(dateStr) || null;
  }
  
  try {
    let result: Date | null = null;
    
    // 특수 키워드 처리
    if (dateStr.toLowerCase().includes('오늘')) {
      result = new Date();
      dateParseCache.set(dateStr, result);
      return result;
    }
    
    if (dateStr.toLowerCase().includes('어제')) {
      const yesterday = new Date();
      yesterday.setDate(yesterday.getDate() - 1);
      result = yesterday;
      dateParseCache.set(dateStr, result);
      return result;
    }
    
    // ISO 형식 (yyyy-MM-dd) 시도
    if (/^\d{4}-\d{2}-\d{2}/.test(dateStr)) {
      const date = parseISO(dateStr);
      if (isValid(date)) {
        dateParseCache.set(dateStr, date);
        return date;
      }
    }
    
    // "M월 d일" 형식 (한국어) 시도
    const koreanDatePattern = /(\d+)월\s*(\d+)일/;
    const koreanMatch = dateStr.match(koreanDatePattern);
    
    if (koreanMatch) {
      const month = parseInt(koreanMatch[1]) - 1; // 0-based month
      const day = parseInt(koreanMatch[2]);
      const date = new Date();
      date.setMonth(month);
      date.setDate(day);
      dateParseCache.set(dateStr, date);
      return date;
    }
    
    // 쉼표 구분 형식 처리 (예: "오늘, 14:52 PM")
    const commaSplit = dateStr.split(',');
    if (commaSplit.length > 1) {
      // 첫 부분이 오늘/어제 등의 키워드인 경우 처리
      const firstPart = commaSplit[0].trim().toLowerCase();
      if (firstPart === '오늘') {
        result = new Date();
        dateParseCache.set(dateStr, result);
        return result;
      } else if (firstPart === '어제') {
        const yesterday = new Date();
        yesterday.setDate(yesterday.getDate() - 1);
        result = yesterday;
        dateParseCache.set(dateStr, result);
        return result;
      }
    }
    
    // parse를 사용한 다양한 형식 시도
    const formats = [
      'yyyy-MM-dd',
      'yyyy/MM/dd',
      'MM-dd-yyyy',
      'MM/dd/yyyy',
      'yyyy년 MM월 dd일',
      'MM월 dd일',
      'yyyy년 M월 d일',
      'M월 d일'
    ];
    
    for (const formatStr of formats) {
      try {
        const date = parse(dateStr, formatStr, new Date(), { locale: ko });
        if (isValid(date)) {
          dateParseCache.set(dateStr, date);
          return date;
        }
      } catch {
        // 이 형식이 실패하면 다음 형식 시도
        continue;
      }
    }
    
    // 위 모든 형식이 실패하면 마지막으로 Date 생성자 시도
    const dateFromConstructor = new Date(dateStr);
    if (isValid(dateFromConstructor)) {
      dateParseCache.set(dateStr, dateFromConstructor);
      return dateFromConstructor;
    }
    
    // 모든 방법이 실패하면 null 반환
    dateParseCache.set(dateStr, null);
    return null;
  } catch (error) {
    console.error(`날짜 파싱 중 오류 발생: ${dateStr}`, error);
    dateParseCache.set(dateStr, null);
    return null;
  }
};

/**
 * 캐시를 정리하는 함수 (필요시 호출)
 */
export const clearDateParseCache = () => {
  dateParseCache.clear();
};

/**
 * Date 객체를 yyyy-MM-dd 형식의 문자열로 변환
 */
export const formatDateToYMD = (date: Date): string => {
  return format(date, 'yyyy-MM-dd');
};

/**
 * 현재 년월 포맷 (yyyy-MM)
 */
export const getCurrentYearMonth = (): string => {
  return format(new Date(), 'yyyy-MM');
};
