/**
 * Zaman bloğu hesaplama yardımcı fonksiyonları
 * 
 * Zaman blokları DB'de TUTULMAZ - runtime'da hesaplanır
 * 
 * Saat aralıkları:
 * - Dawn: 05:00 - 08:00 (3 saat) - Balon uçuşları için
 * - Morning: 09:00 - 12:00 (3 saat)
 * - Afternoon: 12:00 - 17:00 (5 saat)
 * - Evening: 17:00 - 21:00 (4 saat)
 * 
 * Toplam gün süresi: 12 saat aktivite (balon dahil)
 * Varsayılan ziyaret süresi: 2 saat (veya place.duration)
 */

export type TimeBlock = 'dawn' | 'morning' | 'afternoon' | 'evening';

/**
 * Balon uçuşu tespiti - Merkezi kontrol fonksiyonu
 * Balon uçuşları ZORUNLU olarak dawn (05:00-08:00) zaman bloğunda olmalıdır
 */
export function isBalloonActivity(place: any): boolean {
  if (!place) return false;
  
  // Type kontrolü
  if (place.type === 'hot-air-balloon') return true;
  
  // Name kontrolü (fallback)
  const name = (place.name || '').toLowerCase();
  if (name.includes('balon') || name.includes('balloon')) return true;
  
  return false;
}

export interface PlaceWithTimeBlock {
  timeBlock: TimeBlock;
  startTime: string; // HH:MM formatında
  endTime: string; // HH:MM formatında
}

/**
 * Süre string'ini saat cinsine çevirir
 * Örnekler: "2 hours" → 2, "1.5 hours" → 1.5, "90 minutes" → 1.5, "2" → 2
 */
export function parseDuration(duration: string | null | undefined): number {
  if (!duration) return 2; // Varsayılan 2 saat

  const durationStr = duration.toLowerCase().trim();
  
  // Sadece sayı varsa (örn: "2")
  const numOnly = parseFloat(durationStr);
  if (!Number.isNaN(numOnly) && durationStr === numOnly.toString()) {
    return numOnly;
  }

  // "X hours" formatı
  const hoursMatch = durationStr.match(/(\d+\.?\d*)\s*(hour|hours|saat|sa)/i);
  if (hoursMatch) {
    return Number.parseFloat(hoursMatch[1]);
  }

  // "X minutes" formatı
  const minutesMatch = durationStr.match(/(\d+)\s*(minute|minutes|dakika|dk)/i);
  if (minutesMatch) {
    return Number.parseFloat(minutesMatch[1]) / 60;
  }

  // Parse edilemezse varsayılan
  return 2;
}

/**
 * Saat string'ini dakikaya çevirir (09:00 → 540)
 */
function timeToMinutes(time: string): number {
  const [hours, minutes] = time.split(':').map(Number);
  return hours * 60 + minutes;
}

/**
 * Dakikayı saat string'ine çevirir (540 → "09:00")
 */
function minutesToTime(minutes: number): string {
  const hours = Math.floor(minutes / 60);
  const mins = minutes % 60;
  return `${hours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}`;
}

/**
 * Dakika değerine göre zaman bloğunu belirler
 */
function getTimeBlockFromMinutes(minutes: number): TimeBlock {
  const dawnEnd = timeToMinutes('08:00'); // 480
  const morningEnd = timeToMinutes('12:00'); // 720
  const afternoonEnd = timeToMinutes('17:00'); // 1020
  
  if (minutes < dawnEnd) return 'dawn';
  if (minutes < morningEnd) return 'morning';
  if (minutes < afternoonEnd) return 'afternoon';
  return 'evening';
}

/**
 * Yerleri order_index sırasına göre zaman bloklarına atar
 * 
 * ÖNEMLİ: Balon uçuşları ZORUNLU olarak dawn (05:00) saatinde başlar
 * 
 * @param places - Sıralanmış yerler (order_index ASC)
 * @returns Her yer için zaman bloğu bilgisi
 */
export function assignTimeBlocks(places: any[]): Map<string, PlaceWithTimeBlock> {
  const result = new Map<string, PlaceWithTimeBlock>();
  
  // order_index'e göre sıralı olduğundan emin ol
  const sortedPlaces = [...places].sort((a, b) => 
    (a.order_index ?? 0) - (b.order_index ?? 0)
  );

  // Balon kontrolü - balon varsa günün başlangıcı 05:00
  const hasBalloon = sortedPlaces.some(isBalloonActivity);
  let currentMinutes = hasBalloon ? timeToMinutes('05:00') : timeToMinutes('09:00');
  const dayEndMinutes = timeToMinutes('21:00'); // 1260 dakika

  for (const place of sortedPlaces) {
    // Balon için özel işlem - ZORUNLU olarak dawn'da
    if (isBalloonActivity(place)) {
      const balloonStart = '05:00';
      const balloonEnd = '08:00'; // Tipik balon uçuşu 2-3 saat
      
      result.set(place.tripPlaceId || place.id, {
        timeBlock: 'dawn',
        startTime: balloonStart,
        endTime: balloonEnd,
      });
      
      // Balondan sonra 30 dakika transfer + kahvaltı süresi
      currentMinutes = timeToMinutes('08:30');
      continue;
    }
    
    // Normal yerler için işlem
    const durationHours = parseDuration(place.duration);
    const durationMinutes = Math.round(durationHours * 60);
    
    // Başlangıç zamanı
    const startTime = minutesToTime(currentMinutes);
    
    // Bitiş zamanı (gün sonunu aşmayacak şekilde)
    let endMinutes = currentMinutes + durationMinutes;
    if (endMinutes > dayEndMinutes) {
      endMinutes = dayEndMinutes;
    }
    const endTime = minutesToTime(endMinutes);
    
    // Zaman bloğunu belirle (başlangıç zamanına göre)
    const timeBlock = getTimeBlockFromMinutes(currentMinutes);
    
    // Sonucu kaydet (tripPlaceId kullan - aynı place birden fazla günde olabilir)
    const placeId = place.tripPlaceId || place.id;
    result.set(placeId, {
      timeBlock,
      startTime,
      endTime,
    });
    
    // Bir sonraki yer için zamanı güncelle
    currentMinutes = endMinutes;
    
    // Gün sonu aşıldıysa dur
    if (currentMinutes >= dayEndMinutes) {
      // Kalan yerler varsa hepsini evening'e ata
      const remainingPlaces = sortedPlaces.slice(sortedPlaces.indexOf(place) + 1);
      for (const remainingPlace of remainingPlaces) {
        const remainingPlaceId = remainingPlace.tripPlaceId || remainingPlace.id;
        result.set(remainingPlaceId, {
          timeBlock: 'evening',
          startTime: '17:00',
          endTime: '21:00',
        });
      }
      break;
    }
  }
  
  return result;
}

/**
 * Zaman bloğu etiketini döndürür
 */
export function getTimeBlockLabel(block: TimeBlock): string {
  const labels: Record<TimeBlock, string> = {
    dawn: '🌅 Gün Doğumu',
    morning: '☀️ Sabah',
    afternoon: '🌤️ Öğle',
    evening: '🌆 Akşam',
  };
  return labels[block];
}

/**
 * Yerleri zaman bloklarına göre gruplar
 * 
 * @param places - Yerler
 * @param timeBlockMap - assignTimeBlocks() sonucu
 * @returns Zaman bloklarına göre gruplandırılmış yerler
 */
export function groupPlacesByTimeBlock(
  places: any[],
  timeBlockMap: Map<string, PlaceWithTimeBlock>
): Record<TimeBlock, any[]> {
  const groups: Record<TimeBlock, any[]> = {
    dawn: [],
    morning: [],
    afternoon: [],
    evening: [],
  };

  for (const place of places) {
    const placeId = place.tripPlaceId || place.id;
    const timeBlockInfo = timeBlockMap.get(placeId);
    
    if (timeBlockInfo) {
      groups[timeBlockInfo.timeBlock].push({
        ...place,
        startTime: timeBlockInfo.startTime,
        endTime: timeBlockInfo.endTime,
      });
    }
  }

  return groups;
}

/**
 * Boş zaman aralıklarını tespit eder
 * 
 * ÖNEMLİ: Balon varsa gün 05:00'te başlar, yoksa 09:00'da
 * 
 * @param places - Sıralanmış yerler (order_index ASC)
 * @returns Boş zaman blokları
 */
export function detectFreeTimeBlocks(places: any[]): Array<{
  timeBlock: TimeBlock;
  startTime: string;
  endTime: string;
  durationMinutes: number;
}> {
  const freeBlocks: Array<{
    timeBlock: TimeBlock;
    startTime: string;
    endTime: string;
    durationMinutes: number;
  }> = [];

  // Eğer hiç yer yoksa, tüm gün boş
  if (!places || places.length === 0) {
    return [
      {
        timeBlock: 'morning',
        startTime: '09:00',
        endTime: '12:00',
        durationMinutes: 180,
      },
      {
        timeBlock: 'afternoon',
        startTime: '12:00',
        endTime: '17:00',
        durationMinutes: 300,
      },
      {
        timeBlock: 'evening',
        startTime: '17:00',
        endTime: '21:00',
        durationMinutes: 240,
      },
    ];
  }

  // Balon kontrolü - balon varsa dawn bloğu dolu sayılır
  const hasBalloon = places.some(isBalloonActivity);

  // Zaman bloklarını hesapla
  const timeBlockMap = assignTimeBlocks(places);
  
  // Tüm yerleri zaman sırasına göre sırala
  const sortedPlaces = [...places]
    .sort((a, b) => (a.order_index ?? 0) - (b.order_index ?? 0))
    .map(place => {
      const placeId = place.tripPlaceId || place.id;
      const timeInfo = timeBlockMap.get(placeId);
      return {
        ...place,
        ...timeInfo,
      };
    })
    .filter(p => p.startTime && p.endTime);

  // Gün başlangıcı ve bitişi (balon varsa 05:00, yoksa 09:00)
  const dayStart = hasBalloon ? timeToMinutes('05:00') : timeToMinutes('09:00');
  const dayEnd = timeToMinutes('21:00');

  // İlk yerden önceki boşluk
  if (sortedPlaces.length > 0) {
    const firstPlaceStart = timeToMinutes(sortedPlaces[0].startTime);
    if (firstPlaceStart > dayStart) {
      const gapMinutes = firstPlaceStart - dayStart;
      if (gapMinutes >= 60) { // En az 1 saat boşluk varsa
        freeBlocks.push({
          timeBlock: getTimeBlockFromMinutes(dayStart),
          startTime: minutesToTime(dayStart),
          endTime: sortedPlaces[0].startTime,
          durationMinutes: gapMinutes,
        });
      }
    }
  }

  // Yerler arasındaki boşluklar
  for (let i = 0; i < sortedPlaces.length - 1; i++) {
    const currentEnd = timeToMinutes(sortedPlaces[i].endTime);
    const nextStart = timeToMinutes(sortedPlaces[i + 1].startTime);
    const gapMinutes = nextStart - currentEnd;

    if (gapMinutes >= 60) { // En az 1 saat boşluk varsa
      freeBlocks.push({
        timeBlock: getTimeBlockFromMinutes(currentEnd),
        startTime: sortedPlaces[i].endTime,
        endTime: sortedPlaces[i + 1].startTime,
        durationMinutes: gapMinutes,
      });
    }
  }

  // Son yerden sonraki boşluk
  if (sortedPlaces.length > 0) {
    const lastPlaceEnd = timeToMinutes(sortedPlaces[sortedPlaces.length - 1].endTime);
    if (lastPlaceEnd < dayEnd) {
      const gapMinutes = dayEnd - lastPlaceEnd;
      if (gapMinutes >= 60) { // En az 1 saat boşluk varsa
        freeBlocks.push({
          timeBlock: getTimeBlockFromMinutes(lastPlaceEnd),
          startTime: sortedPlaces[sortedPlaces.length - 1].endTime,
          endTime: minutesToTime(dayEnd),
          durationMinutes: gapMinutes,
        });
      }
    }
  }

  return freeBlocks;
}
