
import { supabase } from '@/lib/supabase';
import { Transaction } from '@/components/TransactionCard';
import { isSyncEnabled } from '../syncSettings';
import { formatDateForDisplay } from './dateUtils';
import { getDeletedTransactions, isTransactionDeleted } from './deletedTransactionsTracker';

/**
 * Download transaction data from Supabase to local storage
 * 서버에서 로컬 스토리지로 데이터 다운로드 (병합 방식)
 */
export const downloadTransactions = async (userId: string): Promise<void> => {
  if (!isSyncEnabled()) {
    console.log('[동기화] 다운로드: 동기화 비활성화 상태, 작업 건너뜀');
    return;
  }

  try {
    console.log('[동기화] 서버에서 트랜잭션 데이터 다운로드 시작');
    
    // 다운로드 시간 기록 (충돌 감지용)
    const downloadStartTime = new Date().toISOString();
    console.log(`[동기화] 다운로드 시작 시간: ${downloadStartTime}`);
    
    // 대용량 데이터 처리를 위한 페이지네이션 설정
    const pageSize = 500; // 한 번에 가져올 최대 레코드 수
    let lastId = null;
    let allServerData = [];
    let hasMore = true;
    
    // 페이지네이션을 사용하여 모든 데이터 가져오기
    while (hasMore) {
      let query = supabase
        .from('transactions')
        .select('*')
        .eq('user_id', userId)
        .order('id', { ascending: true })
        .limit(pageSize);
        
      // 마지막 ID 이후의 데이터만 가져오기
      if (lastId) {
        query = query.gt('id', lastId);
      }
      
      const { data, error } = await query;
      
      if (error) {
        console.error('[동기화] 트랜잭션 다운로드 실패:', error);
        console.error('[동기화] 오류 상세:', JSON.stringify(error, null, 2));
        throw error;
      }
      
      if (!data || data.length === 0) {
        hasMore = false;
      } else {
        allServerData = [...allServerData, ...data];
        lastId = data[data.length - 1].id;
        
        // 마지막 페이지인지 확인
        if (data.length < pageSize) {
          hasMore = false;
        }
        
        console.log(`[동기화] 페이지 다운로드 완료: ${data.length}개 항목`);
      }
    }
    
    console.log(`[동기화] 서버 데이터 다운로드 완료: 총 ${allServerData.length}개 항목`);
    
    if (allServerData.length === 0) {
      console.log('[동기화] 서버에 저장된 트랜잭션 없음');
      return; // 서버에 데이터가 없으면 로컬 데이터 유지
    }
    
    // 삭제된 트랜잭션 ID 목록 가져오기
    const deletedIds = getDeletedTransactions();
    console.log(`[동기화] 삭제된 트랜잭션 ${deletedIds.length}개 필터링 적용`);
    
    if (deletedIds.length > 0) {
      console.log(`[동기화] 삭제 추적 항목: ${deletedIds.slice(0, 5).join(', ')}${deletedIds.length > 5 ? '...' : ''}`);
    }
    
    // 서버 데이터를 로컬 형식으로 변환 (삭제된 항목 제외)
    const serverTransactions = allServerData
      .filter(t => {
        const transactionId = t.transaction_id || t.id;
        const isDeleted = isTransactionDeleted(transactionId);
        if (isDeleted) {
          console.log(`[동기화] 삭제된 트랜잭션 필터링: ${transactionId}`);
        }
        return !isDeleted; // 삭제된 항목 제외
      })
      .map(t => {
        try {
          // 날짜 형식 변환 시 오류 방지 처리
          let formattedDate = '날짜 없음';
          try {
            if (t.date) {
              // ISO 형식이 아닌 경우 기본 변환 수행
              if (!t.date.match(/^\d{4}-\d{2}-\d{2}T/)) {
                console.log(`[동기화] 비표준 날짜 형식 감지: ${t.date}, ID: ${t.transaction_id || t.id}`);
                // 유효한 Date 객체로 변환 가능한지 확인
                const testDate = new Date(t.date);
                if (isNaN(testDate.getTime())) {
                  console.warn(`[동기화] 잘못된 날짜 형식 감지, 현재 날짜 사용: ${t.date}`);
                  t.date = new Date().toISOString(); // 잘못된 날짜는 현재 날짜로 대체
                }
              }
              formattedDate = formatDateForDisplay(t.date);
            }
          } catch (err) {
            console.error(`[동기화] 날짜 변환 오류 (ID: ${t.transaction_id || t.id}):`, err);
            // 오류 발생 시 기본값 사용
            formattedDate = new Date().toLocaleString('ko-KR');
          }
          
          return {
            id: t.transaction_id || t.id,
            title: t.title || '무제',
            amount: t.amount || 0,
            date: formattedDate,
            category: t.category || '기타',
            type: t.type || 'expense',
            notes: t.notes || '',
            serverTimestamp: t.updated_at || t.created_at || downloadStartTime
          };
        } catch (itemError) {
          console.error(`[동기화] 트랜잭션 변환 오류 (ID: ${t.transaction_id || t.id}):`, itemError);
          // 오류 발생 시 기본 객체 반환
          return {
            id: t.transaction_id || t.id,
            title: '데이터 오류',
            amount: 0,
            date: new Date().toLocaleString('ko-KR'),
            category: '기타',
            type: 'expense',
            notes: '데이터 변환 중 오류 발생',
            serverTimestamp: downloadStartTime
          };
        }
      });
    
    console.log(`[동기화] 서버 트랜잭션 변환 완료: ${serverTransactions.length}개 항목`);
    
    // 기존 로컬 데이터 불러오기
    const localDataStr = localStorage.getItem('transactions');
    const localTransactions: Transaction[] = localDataStr ? JSON.parse(localDataStr) : [];
    
    console.log(`[동기화] 로컬 트랜잭션: ${localTransactions.length}개 항목`);
    
    // 로컬 데이터와 서버 데이터 병합 (ID 기준)
    const transactionMap = new Map();
    
    // 로컬 데이터를 맵에 추가
    localTransactions.forEach((tx: Transaction) => {
      if (tx && tx.id) { // 유효성 검사 추가
        // 로컬 항목에 타임스탬프 추가 (없는 경우)
        const txWithTimestamp = {
          ...tx,
          localTimestamp: tx.localTimestamp || downloadStartTime
        };
        transactionMap.set(tx.id, txWithTimestamp);
      }
    });
    
    // 충돌 카운터
    let overwrittenCount = 0;
    let preservedCount = 0;
    
    // 서버 데이터로 맵 업데이트 (타임스탬프 비교)
    serverTransactions.forEach(tx => {
      if (tx && tx.id) { // 유효성 검사 추가
        const existingTx = transactionMap.get(tx.id);
        
        if (!existingTx) {
          // 로컬에 없는 새 항목
          transactionMap.set(tx.id, tx);
          console.log(`[동기화] 새 항목 추가: ${tx.id} - ${tx.title}`);
        } else {
          // 타임스탬프 비교로 최신 데이터 결정
          const serverTime = tx.serverTimestamp || downloadStartTime;
          const localTime = existingTx.localTimestamp || '1970-01-01T00:00:00Z';
          
          if (serverTime > localTime) {
            // 서버 데이터가 더 최신
            transactionMap.set(tx.id, tx);
            overwrittenCount++;
            console.log(`[동기화] 서버 데이터로 업데이트: ${tx.id} - ${tx.title} (서버: ${serverTime}, 로컬: ${localTime})`);
          } else {
            // 로컬 데이터 유지
            preservedCount++;
            console.log(`[동기화] 로컬 데이터 유지: ${tx.id} - ${existingTx.title} (서버: ${serverTime}, 로컬: ${localTime})`);
          }
        }
      }
    });
    
    // 최종 병합된 데이터 생성
    const mergedTransactions = Array.from(transactionMap.values());
    
    console.log(`[동기화] 병합 결과: 총 ${mergedTransactions.length}개 항목 (서버 데이터로 업데이트: ${overwrittenCount}, 로컬 데이터 유지: ${preservedCount})`);
    
    // 로컬 스토리지에 저장
    localStorage.setItem('transactions', JSON.stringify(mergedTransactions));
    console.log(`[동기화] 병합된 트랜잭션 저장 완료`);
    
    // 백업 저장
    localStorage.setItem('transactions_backup', JSON.stringify(mergedTransactions));
    console.log(`[동기화] 트랜잭션 백업 저장 완료`);
    
    // 이벤트 발생시켜 UI 업데이트
    window.dispatchEvent(new Event('transactionUpdated'));
    console.log(`[동기화] 트랜잭션 업데이트 이벤트 발생`);
  } catch (error) {
    console.error('[동기화] 트랜잭션 다운로드 중 오류:', error);
    console.error('[동기화] 오류 상세:', JSON.stringify(error, null, 2));
    throw error;
  }
};
