// Edge Function: suggest-places
// AI-powered place suggestions using Gemini 2.5 Flash

import { createClient } from 'jsr:@supabase/supabase-js@2';
import { requireAuth, checkRateLimit } from '../_shared/auth.ts';

const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};

interface ExistingPlace {
  placeId: string;
  name: string;
  lat: number;
  lng: number;
  duration: string;
  order_index: number;
}

interface FreeTimeBlock {
  timeBlock: 'morning' | 'afternoon' | 'evening';
  startTime: string;
  endTime: string;
  durationMinutes: number;
}

interface SuggestPlacesRequest {
  destination: string;
  dayDate: string;
  dayNumber: number;
  existingPlaces?: ExistingPlace[];
  freeTimeBlocks?: FreeTimeBlock[];
  interests?: string[];
  tripHasBalloon?: boolean; // Trip-level constraint: balloon already exists
}

interface PlaceSuggestion {
  placeId: string;
  name: string;
  type: string;
  description: string;
  reason: string;
  suggestedTimeBlock: 'morning' | 'afternoon' | 'evening';
}

Deno.serve(async (req) => {
  // Handle CORS preflight
  if (req.method === 'OPTIONS') {
    return new Response(null, { headers: corsHeaders });
  }

  try {
    // Auth check
    const auth = await requireAuth(req);
    if (auth.error) return auth.error;

    // Rate limit check (20 AI suggestions per hour)
    const supabaseService = createClient(
      Deno.env.get('SUPABASE_URL')!,
      Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
    );
    const rateLimitResponse = await checkRateLimit(auth.userId, 'ai_suggest', supabaseService);
    if (rateLimitResponse) return rateLimitResponse;

    const { 
      destination, 
      dayDate,
      dayNumber, 
      existingPlaces = [], 
      freeTimeBlocks = [],
      interests = [],
      tripHasBalloon = false
    }: SuggestPlacesRequest = await req.json();

    if (!destination) {
      return new Response(
        JSON.stringify({ error: 'Destination is required' }),
        { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      );
    }

    // Get integration API key
    const apiKey = Deno.env.get('INTEGRATIONS_API_KEY');
    if (!apiKey) {
      return new Response(
        JSON.stringify({ error: 'API key not configured' }),
        { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      );
    }

    // Build context-aware AI prompt
    let contextText = '';
    
    // Existing places context
    if (existingPlaces.length > 0) {
      const placesList = existingPlaces
        .map(p => `${p.name} (${p.duration}, sıra: ${p.order_index + 1})`)
        .join(', ');
      contextText += `Kullanıcı zaten şu yerleri eklemiş: ${placesList}. Bu yerleri tekrar önerme.\n`;
      
      // Last place location for proximity
      const lastPlace = existingPlaces[existingPlaces.length - 1];
      if (lastPlace.lat && lastPlace.lng) {
        contextText += `Son eklenen yer: ${lastPlace.name} (${lastPlace.lat}, ${lastPlace.lng}). Yakın yerler öner.\n`;
      }
    }
    
    // Free time blocks context
    if (freeTimeBlocks.length > 0) {
      const timeBlockLabels: Record<string, string> = {
        morning: 'Sabah',
        afternoon: 'Öğle',
        evening: 'Akşam',
      };
      const freeTimeText = freeTimeBlocks
        .map(block => `${timeBlockLabels[block.timeBlock]} (${block.startTime}-${block.endTime}, ${Math.floor(block.durationMinutes / 60)} saat)`)
        .join(', ');
      contextText += `Boş zaman aralıkları: ${freeTimeText}. Bu zaman dilimlerine uygun yerler öner.\n`;
    } else if (existingPlaces.length === 0) {
      contextText += `Gün tamamen boş. Sabah, öğle ve akşam için yerler öner.\n`;
    }
    
    // Interests context
    if (interests.length > 0) {
      contextText += `Kullanıcının ilgi alanları: ${interests.join(', ')}.\n`;
    }

    // Day date context
    if (dayDate) {
      contextText += `Tarih: ${dayDate}.\n`;
    }

    // Trip-level constraints
    if (tripHasBalloon) {
      contextText += `ÖNEMLİ: Bu seyahatte zaten balon uçuşu var. Balon uçuşu (hot-air-balloon) önerme.\n`;
    }

    // First, use Smart Search API to find real places in the destination
    let searchResults: any[] = [];
    try {
      const searchCategories = [
        `${destination} tourist attractions`,
        `${destination} best restaurants cafes`,
        `${destination} activities things to do`,
        `${destination} viewpoints panorama scenic`
      ];

      const searchPromises = searchCategories.map(async (query) => {
        try {
          const searchUrl = `https://app-9w9pd00g5j41-api-VaOwP8E7dKEa.gateway.appmedo.com/search/FgEFxazBTfRUumJx/smart?q=${encodeURIComponent(query)}&count=8&mkt=tr-TR`;
          const searchResponse = await fetch(searchUrl, {
            headers: {
              'X-Gateway-Authorization': `Bearer ${apiKey}`,
            },
          });

          if (searchResponse.ok) {
            const searchData = await searchResponse.json();
            return searchData.webPages?.value || [];
          }
          return [];
        } catch (e) {
          console.error('Search error for query:', query, e);
          return [];
        }
      });

      const allSearchResults = await Promise.all(searchPromises);
      searchResults = allSearchResults.flat().slice(0, 20); // Get top 20 results
    } catch (searchError) {
      console.error('Smart Search API error:', searchError);
      // Continue with AI-only suggestions if search fails
    }

    // Build enhanced context with search results
    let searchContext = '';
    if (searchResults.length > 0) {
      searchContext = '\n\nArama sonuçlarından bulunan gerçek yerler:\n';
      searchResults.slice(0, 15).forEach((result, idx) => {
        searchContext += `${idx + 1}. ${result.name} - ${result.snippet}\n`;
      });
      searchContext += '\nBu gerçek yerlerden uygun olanları öner.\n';
    }

    const prompt = `${destination} şehrinde Gün ${dayNumber} için 8-12 adet turistik yer öner.

${contextText}
${searchContext}

ÇEŞİTLİLİK SAĞLA:
- 3-4 turistik mekan (müze, tarihi alan, anıt, kilise, vadi)
- 2-3 restoran/kafe (kahvaltı, öğle yemeği, akşam yemeği)
- 2-3 aktivite (macera, deneyim, eğlence, tur)
- 1-2 manzara noktası (panorama, fotoğraf noktası, sunset point)

ÖNEMLİ KURALLAR:
1. Önerilen yerler ${destination} şehrinde gerçekten var olan yerler olmalı
2. Her yer için veritabanında arama yapılabilecek tam ve doğru isim ver
3. Boş zaman dilimlerine uygun yerler öner
4. Mevcut yerlere yakın konumdaki yerleri önceliklendir
5. Ziyaret süresini boş zaman miktarına göre ayarla
6. Her kategoriden (turistik mekan, restoran, aktivite, manzara) yer ekle
7. Yukarıdaki arama sonuçlarından gerçek yerleri kullan
${tripHasBalloon ? '8. ASLA balon uçuşu (hot-air-balloon) önerme - trip içinde zaten var\n' : ''}

Her yer için şu bilgileri ver:
- İsim (name): Tam ve doğru yer adı (veritabanında aranabilir)
- Tür (type): museum, restaurant, viewpoint, historical, activity, shopping, cafe gibi
- Kısa açıklama (description): 1-2 cümle
- Neden önerildiği (reason): Kullanıcıya neden uygun olduğunu, hangi boş zamana uyduğunu, neden bu sırada olması gerektiğini açıkla
- Önerilen zaman bloğu (suggestedTimeBlock): "morning", "afternoon" veya "evening" (boş zaman dilimlerine göre)

Yanıtı JSON array formatında ver (8-12 yer):
[
  {
    "name": "Tam yer adı",
    "type": "museum",
    "description": "Kısa açıklama",
    "reason": "Sabah 09:00-11:00 arası boş, Göreme Açık Hava Müzesi'ne yakın, 2 saatlik ziyaret için ideal",
    "suggestedTimeBlock": "morning"
  }
]`;

    // Call AI Search API with timeout
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 saniye timeout

    try {
      const aiResponse = await fetch(
        'https://app-9w9pd00g5j41-api-zYm4ze3j7XvL.gateway.appmedo.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse',
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'X-Gateway-Authorization': `Bearer ${apiKey}`,
          },
          body: JSON.stringify({
            contents: [
              {
                role: 'user',
                parts: [{ text: prompt }],
              },
            ],
          }),
          signal: controller.signal,
        }
      );

      clearTimeout(timeoutId);

      if (!aiResponse.ok) {
        throw new Error(`AI API error: ${aiResponse.status}`);
      }

      // Parse streaming response
      const reader = aiResponse.body?.getReader();
      const decoder = new TextDecoder();
      let fullText = '';

      if (reader) {
        while (true) {
          const { done, value } = await reader.read();
          if (done) break;

          const chunk = decoder.decode(value);
          const lines = chunk.split('\n');

          for (const line of lines) {
            if (line.startsWith('data: ')) {
              try {
                const jsonData = JSON.parse(line.slice(6));
                const text = jsonData.candidates?.[0]?.content?.parts?.[0]?.text;
                if (text) {
                  fullText += text;
                }
              } catch (e) {
                // Skip invalid JSON lines
                console.error('Failed to parse line:', e);
              }
            }
          }
        }
      }

      // Extract JSON from response
      let suggestions: PlaceSuggestion[] = [];
      
      // Try to find JSON array in the response
      const jsonMatch = fullText.match(/\[[\s\S]*\]/);
      if (jsonMatch) {
        try {
          const parsedSuggestions = JSON.parse(jsonMatch[0]);
          
          // For each suggestion, resolve or create the place in the database
          const resolvedSuggestions = await Promise.all(parsedSuggestions.map(async (s: any) => {
            try {
              // Search for the place in the database by name (case-insensitive)
              const { data: existingPlaces, error: searchError } = await supabaseService
                .from('places')
                .select('id, name')
                .ilike('name', `%${s.name}%`)
                .limit(1);

              if (searchError) throw searchError;

              let placeId = '';
              let name = s.name;

              if (existingPlaces && existingPlaces.length > 0) {
                placeId = existingPlaces[0].id;
                name = existingPlaces[0].name;
              } else {
                // If not found, create the place using service role
                const { data: newPlace, error: createError } = await supabaseService
                  .from('places')
                  .insert([
                    {
                      name: s.name,
                      description: s.description || s.reason,
                      type: s.type || 'attraction',
                      city: destination,
                      country: 'Türkiye',
                      duration: '2 saat',
                      region: destination.includes('Cappadocia') || destination.includes('Kapadokya') ? 'Cappadocia' : null
                    }
                  ])
                  .select()
                  .single();

                if (createError) throw createError;
                placeId = newPlace.id;
              }

              return {
                placeId: placeId,
                name: name,
                type: s.type || 'attraction',
                description: s.description || '',
                reason: s.reason || 'Önerilen yer',
                suggestedTimeBlock: s.suggestedTimeBlock || 'morning',
              };
            } catch (e) {
              console.error(`Failed to resolve place ${s.name}:`, e);
              return null;
            }
          }));
          
          suggestions = resolvedSuggestions.filter(s => s !== null) as PlaceSuggestion[];
        } catch (e) {
          console.error('Failed to parse suggestions JSON:', e);
        }
      }

      // Fallback: Create suggestions from search results if no AI suggestions or parsing failed
      if (suggestions.length === 0) {
        const defaultTimeBlock = freeTimeBlocks.length > 0 
          ? freeTimeBlocks[0].timeBlock 
          : 'morning';
        
        // Use search results as fallback if available
        if (searchResults.length > 0) {
          const resolvedFallbacks = await Promise.all(searchResults.slice(0, 8).map(async (result, idx) => {
            try {
              // Search for the place in the database by name
              const { data: existingPlaces } = await supabaseService
                .from('places')
                .select('id')
                .ilike('name', `%${result.name}%`)
                .limit(1);

              let placeId = existingPlaces && existingPlaces.length > 0 ? existingPlaces[0].id : '';
              
              if (!placeId) {
                // Create if not found
                const { data: newPlace } = await supabaseService
                  .from('places')
                  .insert([{
                    name: result.name,
                    description: result.snippet || `${destination} bölgesinde popüler bir yer`,
                    type: 'attraction',
                    city: destination,
                    country: 'Türkiye',
                    duration: '2 saat'
                  }])
                  .select()
                  .single();
                if (newPlace) placeId = newPlace.id;
              }

              // Determine type
              let type = 'attraction';
              const lowerName = result.name.toLowerCase();
              const lowerSnippet = (result.snippet || '').toLowerCase();
              if (lowerName.includes('restaurant') || lowerName.includes('cafe') || lowerSnippet.includes('restaurant')) {
                type = 'restaurant';
              }

              const timeBlocks: ('morning' | 'afternoon' | 'evening')[] = ['morning', 'afternoon', 'evening'];
              const suggestedTimeBlock = timeBlocks[idx % 3];

              return {
                placeId,
                name: result.name,
                type,
                description: result.snippet || `${destination} bölgesinde popüler bir yer`,
                reason: `${destination} bölgesinde önerilen popüler yerlerden biri`,
                suggestedTimeBlock,
              };
            } catch (e) {
              return null;
            }
          }));
          suggestions = resolvedFallbacks.filter(s => s !== null && s.placeId) as PlaceSuggestion[];
        } else {
          // Ultimate fallback - try to find/create "Merkez"
          try {
            const merkezName = `${destination} Merkez`;
            const { data: existingMerkez } = await supabaseService
              .from('places')
              .select('id')
              .ilike('name', merkezName)
              .maybeSingle();

            let placeId = existingMerkez?.id;
            if (!placeId) {
              const { data: newMerkez } = await supabaseService
                .from('places')
                .insert([{
                  name: merkezName,
                  type: 'viewpoint',
                  city: destination,
                  country: 'Türkiye'
                }])
                .select()
                .single();
              placeId = newMerkez?.id;
            }

            if (placeId) {
              suggestions = [{
                placeId,
                name: merkezName,
                type: 'viewpoint',
                description: `${destination} şehrinin en popüler bölgesi`,
                reason: 'Şehri tanımak için ideal bir başlangıç noktası',
                suggestedTimeBlock: defaultTimeBlock,
              }];
            }
          } catch (e) {
            console.error('Ultimate fallback failed:', e);
          }
        }
      }

      return new Response(
        JSON.stringify({ suggestions }),
        { 
          status: 200, 
          headers: { ...corsHeaders, 'Content-Type': 'application/json' } 
        }
      );
    } catch (timeoutError: any) {
      clearTimeout(timeoutId);
      throw timeoutError;
    }

  } catch (error: any) {
    console.error('Error in suggest-places:', error);
    
    // Handle timeout errors specifically
    if (error.name === 'AbortError') {
      return new Response(
        JSON.stringify({ error: 'AI API zaman aşımına uğradı (30s). Lütfen tekrar deneyin.' }),
        { status: 504, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      );
    }
    
    return new Response(
      JSON.stringify({ error: error.message || 'Internal server error' }),
      { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    );
  }
});
