/**
 * Kapadokya Seyahat Kuralları
 * 
 * Bu dosya Kapadokya için özel seyahat planlama kurallarını içerir.
 * AUTO_SEED modunda bu kurallar kullanılarak otomatik plan oluşturulur.
 */

import { Place } from '@/types';

// ============================================================================
// TYPE DEFINITIONS
// ============================================================================

export interface PlaceWithCoordinates extends Place {
  latitude: number;
  longitude: number;
  rating?: number;
  type: string;
}

export interface DayPlace {
  id: string;
  type?: string;
  latitude?: number;
  longitude?: number;
}

export interface RulesContext {
  balloonAdded?: boolean;
}

export interface PlaceWithDistance extends PlaceWithCoordinates {
  distance: number;
}

export interface PlaceWithScore extends PlaceWithCoordinates {
  totalScore: number;
  distance: number;
}

// ============================================================================
// TRIP LEVEL RULES (Seyahat Seviyesi Kurallar)
// ============================================================================

export interface TripRules {
  balloon: {
    max_per_trip: number;
    time_block: 'dawn' | 'sunrise' | 'morning' | 'afternoon' | 'evening';
    preferred_day: number; // 1-based (1 = first day, 2 = second day)
  };
  hotel: {
    max_per_trip: number;
    role: 'base_location';
    show_in_timeline: boolean;
  };
}

export const TRIP_RULES: TripRules = {
  balloon: {
    max_per_trip: 1, // Sadece 1 kez balon uçuşu
    time_block: 'sunrise', // Sadece gün doğumunda
    preferred_day: 2, // Tercihen 2. gün (1 günlük seyahatte 1. gün)
  },
  hotel: {
    max_per_trip: 1, // Tek otel (başlangıç noktası)
    role: 'base_location', // Otel = başlangıç noktası
    show_in_timeline: false, // Timeline'da gösterilmez
  },
};

// ============================================================================
// DAY LEVEL RULES (Gün Seviyesi Kurallar)
// ============================================================================

export interface DayRules {
  max_places: number;
  min_places: number;
  time_blocks: string[];
  min_gap_minutes: number;
}

export const DAY_RULES: DayRules = {
  max_places: 10, // Günde maksimum 10 yer
  min_places: 7, // Günde minimum 7 yer (boş gün olmasın)
  time_blocks: ['morning', 'afternoon', 'evening'], // Zaman blokları
  min_gap_minutes: 30, // Yerler arası minimum 30 dakika
};

// ============================================================================
// PLACE TYPE RULES (Yer Tipi Kuralları)
// ============================================================================

export interface PlaceTypeRule {
  allowed_time_blocks: string[];
  typical_duration_hours: number;
  priority: number; // 1 = highest priority
}

export const PLACE_TYPE_RULES: Record<string, PlaceTypeRule> = {
  'hot-air-balloon': {
    allowed_time_blocks: ['sunrise'], // Sadece gün doğumu
    typical_duration_hours: 3, // 3 saat
    priority: 1, // En yüksek öncelik
  },
  'hot_air_balloon': {
    allowed_time_blocks: ['sunrise'], // Sadece gün doğumu
    typical_duration_hours: 3, // 3 saat
    priority: 1, // En yüksek öncelik
  },
  'museum': {
    allowed_time_blocks: ['morning', 'afternoon'], // Sabah veya öğleden sonra
    typical_duration_hours: 2,
    priority: 3,
  },
  'viewpoint': {
    allowed_time_blocks: ['morning', 'sunset', 'afternoon'], // Sabah, gün batımı veya öğleden sonra
    typical_duration_hours: 1,
    priority: 2,
  },
  'park': {
    allowed_time_blocks: ['morning', 'afternoon'], // Sabah veya öğleden sonra
    typical_duration_hours: 2,
    priority: 3,
  },
  'valley': {
    allowed_time_blocks: ['morning', 'afternoon'], // Sabah veya öğleden sonra
    typical_duration_hours: 2,
    priority: 3,
  },
  'historical_site': {
    allowed_time_blocks: ['morning', 'afternoon'], // Sabah veya öğleden sonra
    typical_duration_hours: 2,
    priority: 3,
  },
  'atv': {
    allowed_time_blocks: ['afternoon'], // Öğleden sonra
    typical_duration_hours: 2,
    priority: 4,
  },
  'horse-riding': {
    allowed_time_blocks: ['afternoon'], // Öğleden sonra
    typical_duration_hours: 2,
    priority: 4,
  },
  'restaurant': {
    allowed_time_blocks: ['lunch'], // Öğlen
    typical_duration_hours: 1.5,
    priority: 5,
  },
  'cafe': {
    allowed_time_blocks: ['lunch'], // Öğlen
    typical_duration_hours: 1,
    priority: 5,
  },
  'hotel': {
    allowed_time_blocks: [], // Timeline'a girmez
    typical_duration_hours: 0,
    priority: 0,
  },
  'default': {
    allowed_time_blocks: ['morning', 'afternoon', 'evening'], // Herhangi bir zaman
    typical_duration_hours: 2,
    priority: 6,
  },
};

// ============================================================================
// PLACE TYPE CATEGORIES (Yer Tipi Kategorileri)
// ============================================================================

/**
 * Yer tiplerini davranışlarına göre kategorize eder
 */
export const PLACE_TYPE_CATEGORIES = {
  // Esnek yerler: Günde 3-4 tane olabilir
  FLEXIBLE: ['museum', 'park', 'viewpoint', 'valley', 'historical_site', 'church', 'cave', 'underground_city'],
  
  // Sınırlı yerler: Günde sadece 1 tane
  LIMITED: ['restaurant', 'cafe'],
  
  // Hariç tutulan yerler: Asla timeline'a eklenmez
  EXCLUDED: ['hotel', 'accommodation', 'lodging'],
  
  // Sabit saatli yerler: Trip seviyesinde özel kurallar
  FIXED_TIME: ['hot_air_balloon', 'hot-air-balloon'],
};

/**
 * Bir yerin hangi kategoriye ait olduğunu döndürür
 */
export function getPlaceCategory(placeType: string): 'FLEXIBLE' | 'LIMITED' | 'EXCLUDED' | 'FIXED_TIME' | 'UNKNOWN' {
  if (PLACE_TYPE_CATEGORIES.FLEXIBLE.includes(placeType)) return 'FLEXIBLE';
  if (PLACE_TYPE_CATEGORIES.LIMITED.includes(placeType)) return 'LIMITED';
  if (PLACE_TYPE_CATEGORIES.EXCLUDED.includes(placeType)) return 'EXCLUDED';
  if (PLACE_TYPE_CATEGORIES.FIXED_TIME.includes(placeType)) return 'FIXED_TIME';
  return 'UNKNOWN';
}

// ============================================================================
// DUPLICATION POLICY (Tekrar Politikası)
// ============================================================================

export interface DuplicationPolicy {
  same_place_multiple_days: boolean;
  same_activity_type_same_day: boolean; // DEPRECATED: Artık type-based rules kullanılıyor
}

export const DUPLICATION_POLICY: DuplicationPolicy = {
  same_place_multiple_days: false, // Aynı yer birden fazla günde olamaz
  same_activity_type_same_day: false, // DEPRECATED: Artık kullanılmıyor, type-based rules geçerli
};

// ============================================================================
// HELPER FUNCTIONS (Yardımcı Fonksiyonlar)
// ============================================================================

/**
 * Balon uçuşunun eklenip eklenmeyeceğini kontrol eder
 */
export function shouldAddBalloon(
  dayIndex: number,
  totalDays: number,
  interests: string[],
  tripHasBalloon: boolean
): boolean {
  // Eğer trip zaten balon içeriyorsa, ekleme
  if (tripHasBalloon) {
    return false;
  }

  // Eğer ilgi alanlarında balon yoksa, ekleme
  if (!interests.includes('balloon')) {
    return false;
  }

  // 1 günlük seyahatte 1. gün
  if (totalDays === 1) {
    return dayIndex === 0;
  }

  // Çok günlük seyahatte 2. gün (index 1)
  return dayIndex === 1;
}

/**
 * Yer tipine göre izin verilen zaman bloklarını döndürür
 */
export function getAllowedTimeBlocks(placeType: string): string[] {
  const rule = PLACE_TYPE_RULES[placeType] || PLACE_TYPE_RULES.default;
  return rule.allowed_time_blocks;
}

/**
 * Yer tipine göre tipik süreyi döndürür
 */
export function getTypicalDuration(placeType: string): string {
  const rule = PLACE_TYPE_RULES[placeType] || PLACE_TYPE_RULES.default;
  return `${rule.typical_duration_hours} saat`;
}

/**
 * Yer tipine göre önceliği döndürür
 */
export function getPlacePriority(placeType: string): number {
  const rule = PLACE_TYPE_RULES[placeType] || PLACE_TYPE_RULES.default;
  return rule.priority;
}

/**
 * Yerin belirli bir günde geçerli olup olmadığını kontrol eder
 * YENİ MANTIK: Type-based soft rules
 */
export function isValidForDay(
  place: PlaceWithCoordinates,
  dayPlaces: DayPlace[],
  usedPlaceIds: Set<string>,
  rulesContext?: RulesContext
): boolean {
  // 1️⃣ Aynı yer tekrar eklenemez (trip seviyesi kural)
  if (usedPlaceIds.has(place.id)) {
    return false;
  }

  const placeType = place.type || 'default';
  const category = getPlaceCategory(placeType);

  // 2️⃣ Hotel asla eklenmez
  if (category === 'EXCLUDED') {
    return false;
  }

  // 3️⃣ Balloon constraint (trip seviyesi)
  if (category === 'FIXED_TIME' && rulesContext?.balloonAdded) {
    return false;
  }

  // 4️⃣ LIMITED types: Günde sadece 1 tane (restaurant, cafe)
  if (category === 'LIMITED') {
    const hasLimitedType = dayPlaces.some((p) => {
      const pCategory = getPlaceCategory(p.type || 'default');
      return pCategory === 'LIMITED';
    });
    return !hasLimitedType;
  }

  // 5️⃣ FLEXIBLE types: Serbest (museum, park, viewpoint vb.)
  // Aynı type'tan birden fazla olabilir
  if (category === 'FLEXIBLE') {
    return true;
  }

  // 6️⃣ UNKNOWN types: Varsayılan olarak izin ver
  return true;
}

/**
 * İki nokta arasındaki mesafeyi hesaplar (Haversine formülü, km)
 */
export function haversineDistance(
  lat1: number,
  lng1: number,
  lat2: number,
  lng2: number
): number {
  const R = 6371; // Dünya'nın yarıçapı (km)
  const dLat = toRad(lat2 - lat1);
  const dLng = toRad(lng2 - lng1);
  
  const a =
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
    Math.sin(dLng / 2) * Math.sin(dLng / 2);
  
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  const distance = R * c;
  
  return distance;
}

/**
 * Yerlerin merkez noktasını (centroid) hesaplar
 */
export function getCentroid(places: PlaceWithCoordinates[]): { lat: number; lng: number } {
  if (places.length === 0) {
    return { lat: 0, lng: 0 };
  }

  let totalLat = 0;
  let totalLng = 0;
  let count = 0;

  for (const place of places) {
    if (place.latitude && place.longitude) {
      totalLat += place.latitude;
      totalLng += place.longitude;
      count++;
    }
  }

  if (count === 0) {
    return { lat: 0, lng: 0 };
  }

  return {
    lat: totalLat / count,
    lng: totalLng / count,
  };
}

/**
 * Restaurant adaylarını günün merkezine yakınlığa göre sıralar
 * @param restaurants - Restaurant adayları
 * @param centerLat - Günün merkez noktası (latitude)
 * @param centerLng - Günün merkez noktası (longitude)
 * @param maxDistanceKm - Maksimum mesafe (km), varsayılan 1.5 km
 * @returns Mesafeye göre sıralanmış restaurant listesi
 */
export function findNearestRestaurants(
  restaurants: PlaceWithCoordinates[],
  centerLat: number,
  centerLng: number,
  maxDistanceKm: number = 1.5
): PlaceWithDistance[] {
  return restaurants
    .map((r) => ({
      ...r,
      distance: haversineDistance(centerLat, centerLng, r.latitude || 0, r.longitude || 0),
    }))
    .filter((r) => r.distance < maxDistanceKm)
    .sort((a, b) => a.distance - b.distance);
}

/**
 * İlgi alanlarına göre yerleri filtreler
 */
export function getPlacesByInterests(allPlaces: PlaceWithCoordinates[], interests: string[]): PlaceWithCoordinates[] {
  if (interests.length === 0) {
    // İlgi alanı yoksa en popüler yerleri döndür
    return allPlaces
      .filter(p => p.rating && p.rating > 0)
      .sort((a, b) => (b.rating || 0) - (a.rating || 0));
  }

  // İlgi alanı tag'lerine çevir
  const interestMap: Record<string, string> = {
    'balloon': 'Sıcak Hava Balonu',
    'nature': 'Doğa ve Yürüyüş',
    'history': 'Tarih ve Kültür',
    'photography': 'Fotoğraf Çekimi',
    'adventure': 'Aktivite/Macera',
    'gastronomy': 'Gastronomi',
  };

  const tags = interests.map(i => interestMap[i]).filter(Boolean);

  // İlgi alanlarına göre puanla
  return allPlaces
    .map(place => {
      let score = place.rating || 0;
      const placeTags = place.tags || [];
      
      // Eşleşen tag'ler için bonus puan
      const matchingTags = tags.filter(tag => placeTags.includes(tag));
      score += matchingTags.length * 2;
      
      return { ...place, score, matchingTags };
    })
    .sort((a, b) => b.score - a.score);
}

/**
 * Yerleri mesafe ve popülerliğe göre sıralar
 */
export function rankPlacesByDistanceAndPopularity(
  places: PlaceWithCoordinates[],
  day: DayPlace,
  startLat?: number,
  startLng?: number
): PlaceWithScore[] {
  // Eğer başlangıç noktası varsa, mesafeye göre de puanla
  if (startLat && startLng) {
    return places
      .map(place => {
        const distance = calculateDistance(
          startLat,
          startLng,
          place.latitude || 0,
          place.longitude || 0
        );
        
        // Mesafe puanı (yakın yerler daha yüksek puan)
        const distanceScore = Math.max(0, 100 - distance);
        
        // Popülerlik puanı
        const popularityScore = (place.rating || 0) * 10;
        
        // Toplam puan (popülerlik %60, mesafe %40)
        const totalScore = popularityScore * 0.6 + distanceScore * 0.4;
        
        return { ...place, totalScore, distance };
      })
      .sort((a, b) => b.totalScore - a.totalScore);
  }

  // Başlangıç noktası yoksa sadece popülerliğe göre sırala
  return places
    .map(place => ({
      ...place,
      totalScore: (place.rating || 0) * 10,
      distance: 0
    }))
    .sort((a, b) => (b.rating || 0) - (a.rating || 0));
}

/**
 * İki nokta arasındaki mesafeyi hesaplar (km)
 */
function calculateDistance(lat1: number, lng1: number, lat2: number, lng2: number): number {
  const R = 6371; // Dünya'nın yarıçapı (km)
  const dLat = toRad(lat2 - lat1);
  const dLng = toRad(lng2 - lng1);
  
  const a =
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
    Math.sin(dLng / 2) * Math.sin(dLng / 2);
  
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  const distance = R * c;
  
  return distance;
}

function toRad(degrees: number): number {
  return degrees * (Math.PI / 180);
}

// ============================================================================
// CONSTANTS
// ============================================================================

export const MAX_PLACES_PER_DAY = DAY_RULES.max_places;
export const MIN_PLACES_PER_DAY = DAY_RULES.min_places;

// Balon yeri (sabit)
export const BALLOON_PLACE_TYPE = 'hot-air-balloon';
