     1→import Foundation
     2→import CoreLocation
     3→
     4→/// Lightweight model for storing favorite restaurants
     5→struct FavoriteRestaurant: Codable, Identifiable, Hashable {
     6→    let id: UUID
     7→    let name: String
     8→    let address: String
     9→    let latitude: Double
    10→    let longitude: Double
    11→    let phoneNumber: String?
    12→    let addedAt: Date
    13→
    14→    var coordinate: CLLocationCoordinate2D {
    15→        CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    16→    }
    17→
    18→    init(from restaurant: Restaurant) {
    19→        self.id = restaurant.id
    20→        self.name = restaurant.name
    21→        self.address = restaurant.address
    22→        self.latitude = restaurant.coordinate.latitude
    23→        self.longitude = restaurant.coordinate.longitude
    24→        self.phoneNumber = restaurant.phoneNumber
    25→        self.addedAt = Date()
    26→    }
    27→}
    28→
    29→/// Service for managing favorite restaurants
    30→@MainActor
    31→class FavoritesService: ObservableObject {
    32→
    33→    // MARK: - Published State
    34→
    35→    @Published private(set) var favorites: [FavoriteRestaurant] = []
    36→
    37→    // MARK: - Storage Keys
    38→
    39→    private let favoritesKey = "FoodFinder_Favorites"
    40→
    41→    // MARK: - Singleton
    42→
    43→    static let shared = FavoritesService()
    44→
    45→    // MARK: - Initialization
    46→
    47→    init() {
    48→        loadFavorites()
    49→    }
    50→
    51→    // MARK: - Public Methods
    52→
    53→    /// Check if a restaurant is favorited
    54→    func isFavorite(_ restaurant: Restaurant) -> Bool {
    55→        favorites.contains { $0.id == restaurant.id }
    56→    }
    57→
    58→    /// Check if a restaurant ID is favorited
    59→    func isFavorite(id: UUID) -> Bool {
    60→        favorites.contains { $0.id == id }
    61→    }
    62→
    63→    /// Add a restaurant to favorites
    64→    func addFavorite(_ restaurant: Restaurant) {
    65→        guard !isFavorite(restaurant) else { return }
    66→
    67→        let favorite = FavoriteRestaurant(from: restaurant)
    68→        favorites.insert(favorite, at: 0)
    69→        saveFavorites()
    70→    }
    71→
    72→    /// Remove a restaurant from favorites
    73→    func removeFavorite(_ restaurant: Restaurant) {
    74→        favorites.removeAll { $0.id == restaurant.id }
    75→        saveFavorites()
    76→    }
    77→
    78→    /// Remove a favorite by ID
    79→    func removeFavorite(id: UUID) {
    80→        favorites.removeAll { $0.id == id }
    81→        saveFavorites()
    82→    }
    83→
    84→    /// Toggle favorite status
    85→    func toggleFavorite(_ restaurant: Restaurant) {
    86→        if isFavorite(restaurant) {
    87→            removeFavorite(restaurant)
    88→        } else {
    89→            addFavorite(restaurant)
    90→        }
    91→    }
    92→
    93→    /// Clear all favorites
    94→    func clearAll() {
    95→        favorites = []
    96→        saveFavorites()
    97→    }
    98→
    99→    // MARK: - Private Methods
   100→
   101→    private func loadFavorites() {
   102→        guard let data = UserDefaults.standard.data(forKey: favoritesKey) else {
   103→            favorites = []
   104→            return
   105→        }
   106→
   107→        do {
   108→            favorites = try JSONDecoder().decode([FavoriteRestaurant].self, from: data)
   109→        } catch {
   110→            print("Failed to load favorites: \(error)")
   111→            favorites = []
   112→        }
   113→    }
   114→
   115→    private func saveFavorites() {
   116→        do {
   117→            let data = try JSONEncoder().encode(favorites)
   118→            UserDefaults.standard.set(data, forKey: favoritesKey)
   119→        } catch {
   120→            print("Failed to save favorites: \(error)")
   121→        }
   122→    }
   123→}
   124→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import Foundation
import CoreLocation

/// Lightweight model for storing favorite restaurants
struct FavoriteRestaurant: Codable, Identifiable, Hashable {
    let id: UUID
    let name: String
    let address: String
    let latitude: Double
    let longitude: Double
    let phoneNumber: String?
    let addedAt: Date

    var coordinate: CLLocationCoordinate2D {
        CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    }

    init(from restaurant: Restaurant) {
        self.id = restaurant.id
        self.name = restaurant.name
        self.address = restaurant.address
        self.latitude = restaurant.coordinate.latitude
        self.longitude = restaurant.coordinate.longitude
        self.phoneNumber = restaurant.phoneNumber
        self.addedAt = Date()
    }
}

/// Service for managing favorite restaurants
@MainActor
class FavoritesService: ObservableObject {

    // MARK: - Published State

    @Published private(set) var favorites: [FavoriteRestaurant] = []

    // MARK: - Storage Keys

    private let favoritesKey = "FoodFinder_Favorites"

    // MARK: - Singleton

    static let shared = FavoritesService()

    // MARK: - Initialization

    init() {
        loadFavorites()
    }

    // MARK: - Public Methods

    /// Check if a restaurant is favorited
    func isFavorite(_ restaurant: Restaurant) -> Bool {
        favorites.contains { $0.id == restaurant.id }
    }

    /// Check if a restaurant ID is favorited
    func isFavorite(id: UUID) -> Bool {
        favorites.contains { $0.id == id }
    }

    /// Add a restaurant to favorites
    func addFavorite(_ restaurant: Restaurant) {
        guard !isFavorite(restaurant) else { return }

        let favorite = FavoriteRestaurant(from: restaurant)
        favorites.insert(favorite, at: 0)
        saveFavorites()
    }

    /// Remove a restaurant from favorites
    func removeFavorite(_ restaurant: Restaurant) {
        favorites.removeAll { $0.id == restaurant.id }
        saveFavorites()
    }

    /// Remove a favorite by ID
    func removeFavorite(id: UUID) {
        favorites.removeAll { $0.id == id }
        saveFavorites()
    }

    /// Toggle favorite status
    func toggleFavorite(_ restaurant: Restaurant) {
        if isFavorite(restaurant) {
            removeFavorite(restaurant)
        } else {
            addFavorite(restaurant)
        }
    }

    /// Clear all favorites
    func clearAll() {
        favorites = []
        saveFavorites()
    }

    // MARK: - Private Methods

    private func loadFavorites() {
        guard let data = UserDefaults.standard.data(forKey: favoritesKey) else {
            favorites = []
            return
        }

        do {
            favorites = try JSONDecoder().decode([FavoriteRestaurant].self, from: data)
        } catch {
            print("Failed to load favorites: \(error)")
            favorites = []
        }
    }

    private func saveFavorites() {
        do {
            let data = try JSONEncoder().encode(favorites)
            UserDefaults.standard.set(data, forKey: favoritesKey)
        } catch {
            print("Failed to save favorites: \(error)")
        }
    }
}


total 16
drwxr-xr-x@  5 neog  staff   160 Dec 17 21:56 .
drwxr-xr-x@ 30 neog  staff   960 Dec 17 19:44 ..
-rw-------@  1 neog  staff  4910 Dec 17 21:56 CLAUDE.md
drwxr-xr-x@  9 neog  staff   288 Dec 17 19:47 FoodFinder-iOS
drwxr-xr-x@  5 neog  staff   160 Dec 17 22:08 FoodFinder-iOS.xcodeproj


Perfect! I have now thoroughly explored the FoodFinder iOS app. Let me compile my detailed analysis:

## Detailed Analysis: FoodFinder iOS Enhancement Opportunities

Based on my comprehensive exploration of the FoodFinder iOS codebase, here's a detailed analysis of the current implementation and enhancement possibilities:

---

### CURRENT STATE ASSESSMENT

#### 1. **ClaudeService Implementation** (Lines 1-211)
**Current Capabilities:**
- Single-turn question handling with restaurant context
- Provides up to 15 restaurants sorted by distance
- System prompt in Portuguese (pt-BR)
- Max output: 1024 tokens
- API Key: Hardcoded (security issue)
- Model: Claude Sonnet 4 (claude-sonnet-4-20250514)

**Data Available to Claude:**
```
- Restaurant name, category, distance, address, phone
- User favorites (up to 10 stored)
- Selected food category
- NO: Menus, ratings, hours, WhatsApp info, reviews, pricing
```

**Limitations:**
- Single-round conversations (no history context)
- No state machine for contextual follow-ups
- Claude only sees 15 restaurants max (can miss good options further away)
- No opportunity scoring logic
- No proactive recommendations feature

#### 2. **Restaurant Model** (Restaurant.swift)
**Available Data Points:**
```
✓ ID, name, category, phone, URL
✓ Coordinates, address, distance
✓ MapKit integration
```

**Missing Data:**
```
✗ Opening hours
✗ Ratings/reviews
✗ Menu items/prices
✗ Instagram/WhatsApp handle
✗ Average spend amount
✗ Cuisine specialties
✗ Dietary accommodations
✗ Wait time estimates
```

#### 3. **RestaurantService** (RestaurantService.swift)
**Current Approach:**
- Uses MapKit MKLocalSearch (Apple's local database)
- 2km search radius (fixed)
- 9 hardcoded food categories
- Results sorted by distance only

**Gaps:**
- No enrichment pipeline
- No caching strategy
- Can't reach Google Places, Yelp, or restaurant websites
- No external data source integration

#### 4. **AI Chat Integration** (AIChatView.swift)
**Current Flow:**
```
User Message → ClaudeService.askAboutRestaurants()
  ↓
Claude analyzes: Nearby restaurants + User favorites
  ↓
Single response (no history)
```

**Issues:**
- No conversation memory
- Can't do follow-up questions about the same restaurant
- No ability to track "which restaurant I mentioned"
- Quick suggestions are hardcoded (4 options)

---

### DATA ENRICHMENT OPPORTUNITIES

#### 1. **Menu & Pricing Data Sources**

**Google Places API** (Primary)
```
✓ Business info: hours, ratings, reviews
✓ Menu items/prices: Some restaurants provide
✓ Photos: User-generated food photos
✓ Website: Direct link to restaurant
Cost: Free (limited) to $7/request
Integration: REST API + URLSession
```

**Yelp API**
```
✓ Menu data: Limited but curated
✓ Ratings breakdown: 1-5 stars with comment text
✓ Photos: Professional food photography
✓ Business info: Hours, price range, attributes
Cost: $0.50-$1.50 per request
Integration: OAuth 2.0 + REST API
```

**Restaurant Websites (Web Scraping)**
```
✓ Real-time menus (most restaurants have these)
✓ Accurate pricing
✓ Special offers
✓ Reservation availability
Challenge: Varied HTML structures
Solution: Use a headless browser service (Cheerio, Jsoup)
```

**Meta Business Suite / Facebook Graph API**
```
✓ Hours + special hours
✓ Menu link
✓ Call-to-action buttons
✓ Business category
Cost: Free if you have business access
```

#### 2. **WhatsApp Contact Discovery**

**Current Gap:** No WhatsApp contact validation

**Options:**

**Option A: Cloud API Integration**
- **Twilio WhatsApp API** - Validate phone has WhatsApp (costs ≈ $0.01/check)
- **WhatsApp Business API** - Official integration (requires Meta approval)
- **Local business tools** - Apps like GetContact aggregate WhatsApp numbers

**Option B: Manual Verification**
- Store user-reported WhatsApp numbers in local database
- Build community database of confirmed contacts
- Surface phone number + WhatsApp indicator

**Option C: URL-based (No API needed)**
```
Pattern: https://wa.me/{phoneNumber}
Usage: Can detect if WhatsApp app opens successfully
Cost: Zero
Limitation: Only works on device with WhatsApp installed
```

#### 3. **Opportunity Scoring System**

**Current State:** None - all restaurants equal

**Proposed Scoring Formula:**
```
Opportunity Score =
  (Distance Weight × Normalized_Distance) +
  (Relevance Weight × Category_Match) +
  (Favorites Weight × Recommendation_History) +
  (Popularity Weight × Ratings) +
  (Novelty Weight × User_Visit_Frequency) +
  (Context Weight × Current_Time/Hours)

Parameters:
- Distance Weight: 0.15 (closer = better)
- Relevance: 0.25 (matches selected category)
- Favorites: 0.20 (aligns with past choices)
- Popularity: 0.15 (ratings + review count)
- Novelty: 0.15 (haven't visited recently)
- Context: 0.10 (open at current time?)
```

**Implementation Location:** New class `RestaurantScoringService`

#### 4. **Proactive Recommendations**

**Current Behavior:** Reactive - waits for user questions

**Enhancement Options:**

**Option A: Time-based Suggestions**
```
11:00 AM → "Lunch time! Top pizzerias nearby"
17:00 PM → "Happy hour coming! Bar specials"
20:00 PM → "Dinner rush - romantic restaurants"
```

**Option B: Context-based Suggestions**
```
User at coffee shop → "Try this bakery 200m away"
User near work → "Quick lunch options"
Rainy day → "Delivery-friendly restaurants"
```

**Option C: ML-based Pattern Recognition**
```
User frequents Italian restaurants on Friday?
→ Suggest new Italian place Friday evening
User hasn't tried sushi in 60 days?
→ "You loved sushi before, try this new place"
```

---

### PROPOSED ENHANCEMENT ARCHITECTURE

#### Phase 1: Enhanced Data Model
```swift
// Add to Restaurant.swift
struct EnrichedRestaurant {
    let base: Restaurant

    // Menu & Pricing
    let menuItems: [MenuItem]?
    let priceRange: String?  // "$", "$$", "$$$", "$$$$"
    let averageSpend: Double?

    // Contact
    let whatsappNumber: String?
    let hasWhatsApp: Bool
    let deliveryApps: [DeliveryApp]?

    // Reputation
    let googleRating: Double?
    let yelpRating: Double?
    let reviewCount: Int?
    let reviewHighlights: [String]?

    // Operational
    let hours: BusinessHours?
    let isOpenNow: Bool
    let averageWaitTime: Int?

    // Personalization
    let opportunityScore: Double
    let reasonsToVisit: [String]
    let lastVisitedDate: Date?
}

enum DeliveryApp: String {
    case ifood, uber_eats, rappi
}

struct MenuItem {
    let name: String
    let description: String?
    let price: Double?
    let category: String?
    let isVegetarian: Bool
    let isVegan: Bool
}
```

#### Phase 2: Data Enrichment Service
```
RestaurantEnrichmentService
├── GooglePlacesAdapter
│   ├── searchByPlaceId(restaurant) → GooglePlace
│   ├── getMenu(placeId) → [MenuItem]
│   └── getRatings(placeId) → Rating
├── YelpAdapter
│   ├── searchByPhone(number) → YelpBusiness
│   └── getMenuLink(id) → URL
├── WebScraperAdapter
│   ├── fetchMenu(restaurantUrl) → [MenuItem]
│   └── parseHours(html) → BusinessHours
└── CacheManager
    └── storeEnrichedData(timeout: 24h)
```

#### Phase 3: Enhanced Claude Integration
```
ClaudeService v2
├── askWithContext()  ← New: full enriched data
├── askFollowUp()     ← New: conversation memory
├── scoreRestaurants()  ← New: ranking algorithm
└── getProactiveRecommendation()  ← New: time/context
```

#### Phase 4: Conversation Memory
```swift
class ConversationManager {
    @Published var conversationHistory: [MessageContext] = []

    func addContext(restaurant: EnrichedRestaurant) {
        conversationHistory.append(
            MessageContext(
                restaurantId: restaurant.base.id,
                mentionedAt: Date(),
                details: restaurant
            )
        )
    }

    func buildContextForFollowUp() -> String {
        // Claude can reference previous restaurants
    }
}
```

---

### IMPLEMENTATION ROADMAP

#### **Week 1: Foundation**
1. Add API configuration service (secure key storage)
2. Implement Google Places adapter (basic search + caching)
3. Add menu/pricing to Restaurant model
4. Implement local caching (Core Data or UserDefaults)

#### **Week 2: WhatsApp & Validation**
1. Integrate WhatsApp URL scheme detection
2. Add WhatsApp validation UI
3. Build local database of verified numbers
4. Enhance RestaurantDetailView with WhatsApp button

#### **Week 3: Opportunity Scoring**
1. Implement RestaurantScoringService
2. Add scoring UI component (sparkle badges)
3. Integrate with list sorting
4. Test weighting algorithm

#### **Week 4: AI Enhancement**
1. Add conversation history to ClaudeService
2. Implement context-aware follow-ups
3. Build proactive recommendation system
4. Test multi-turn conversations

#### **Week 5: Polish & Testing**
1. Performance optimization (lazy enrichment)
2. Error handling for API failures
3. Offline mode (serve cached data)
4. Analytics tracking

---

### EXTERNAL DATA SOURCE COMPARISON

| Source | Menu | Prices | Hours | Ratings | API Cost | Quality |
|--------|------|--------|-------|---------|----------|---------|
| **Google Places** | Partial | Partial | Yes | Yes | $7/req | Excellent |
| **Yelp** | Limited | Limited | Yes | Yes | $0.50/req | Very Good |
| **Web Scraping** | Complete | Complete | Yes | No | Server cost | Variable |
| **Meta API** | Yes | No | Yes | No | Free | Good |
| **MapKit Native** | No | No | Partial | No | Free | Limited |
| **Instagram** | Yes* | No | Yes* | Yes* | API cost | Real-time |

*Requires Instagram Graph API access; approval needed

---

### QUICK WINS (No Major Refactoring)

1. **Add WhatsApp Button** (2 hours)
   - Parse phone, create wa.me link, add to RestaurantDetailView

2. **Store Last Visit Dates** (1 hour)
   - Track "visited" timestamp in FavoritesService
   - Show "Last visited 3 weeks ago" in list

3. **Improve Quick Suggestions** (1 hour)
   - Make dynamic based on user's favorite cuisines
   - Change based on time of day

4. **Add Distance Filter** (30 min)
   - Current: 2km fixed
   - Enhancement: Allow user to select radius (1km, 2km, 5km)

5. **Restaurant Grouping** (1 hour)
   - Sort by "distance", "rating", "favorites"
   - Show grouped by cuisine type

---

### SECURITY CONSIDERATIONS

**Critical Issue:** API key hardcoded in ClaudeService.swift (line 14)

**Fix:**
```swift
// Move to Info.plist or environment variable
private let apiKey = Bundle.main.infoDictionary?["CLAUDE_API_KEY"] as? String
```

**For external APIs:**
- Use backend proxy (don't expose keys to client)
- Implement rate limiting
- Add API request signing
- Monitor for abuse

---

### ESTIMATED EFFORT & ROI

| Feature | Effort | User Impact |
|---------|--------|-------------|
| WhatsApp integration | 4 hours | High - Direct contact |
| Menu fetching (Google) | 16 hours | Very High - Informs decisions |
| Opportunity scoring | 12 hours | Medium - Better suggestions |
| Conversation memory | 8 hours | High - Better UX |
| Proactive recommendations | 10 hours | Medium - Discovery |
| Hours + Open now | 4 hours | Medium - Practical info |

**Total: ~54 hours** of implementation for complete enhancement suite

---

### NEXT STEPS

1. **Choose primary data source** - Google Places API for breadth + web scraping for depth
2. **Set up backend proxy** - Never expose API keys from iOS client
3. **Implement gradual enrichment** - Load basic data first, enrich in background
4. **Plan conversation UX** - How to surface related previous recommendations?
5. **Define scoring weights** - A/B test different weightings with users

This analysis provides a complete roadmap for transforming FoodFinder from a basic location-based restaurant finder into an AI-powered, data-enriched discovery platform.