fix_errors.py 8.5 KB
#!/usr/bin/env python3
"""Fix the 10 remaining analysis errors."""
PATH = 'lib/pages/agent/agent_chat_page.dart'

with open(PATH, 'r') as f:
    c = f.read()

# ===== Fix 1: Remove duplicate _maybeEnterReservationFlow (my version at line ~321) =====
# The original at line ~630 already exists. Replace my duplicate with nothing.
dup_maybe = '''
  void _maybeEnterReservationFlow(String text) {
    final ReservationImageParseResult parsed = ReservationImageParser.parse(text);
    if (parsed.hasAny) _startReservationConversation(parsed);
  }'''
if dup_maybe in c:
    c = c.replace(dup_maybe, '', 1)
    print("Removed duplicate _maybeEnterReservationFlow")
else:
    print("WARNING: duplicate _maybeEnterReservationFlow not found")

# ===== Fix 2: Remove duplicate _normalizeReservationDate (my version) =====
# Find the one right after _mergeReservation (line ~130 area)
dup_norm = '''
  ReservationImageParseResult _normalizeReservationDate(ReservationImageParseResult result) {
    final DateTime now = DateTime.now();
    String date = result.date.trim();
    if (date.isEmpty) return result;
    if (date == '今天' || date == '今日') {
      date = '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}';
    } else if (date == '明天' || date == '明日') {
      final DateTime t = now.add(const Duration(days: 1));
      date = '${t.year}-${t.month.toString().padLeft(2, '0')}-${t.day.toString().padLeft(2, '0')}';
    } else if (date == '后天') {
      final DateTime t = now.add(const Duration(days: 2));
      date = '${t.year}-${t.month.toString().padLeft(2, '0')}-${t.day.toString().padLeft(2, '0')}';
    } else if (RegExp(r'^\\d{1,2}月\\d{1,2}日$').hasMatch(date)) {
      final Match? m = RegExp(r'(\\d{1,2})月(\\d{1,2})日').firstMatch(date);
      if (m != null) {
        final int month = int.parse(m.group(1)!);
        final int day = int.parse(m.group(2)!);
        int year = now.year;
        if (DateTime(year, month, day).isBefore(DateTime(now.year, now.month, now.day))) year++;
        date = '$year-${month.toString().padLeft(2, '0')}-${day.toString().padLeft(2, '0')}';
      }
    }
    return ReservationImageParseResult(name: result.name, sex: result.sex, phone: result.phone,
      party: result.party, date: date, meal: result.meal, time: result.time,
      table: result.table, remark: result.remark, rawText: result.rawText);
  }'''

if dup_norm in c:
    c = c.replace(dup_norm, '', 1)
    print("Removed duplicate _normalizeReservationDate")
else:
    print("WARNING: duplicate _normalizeReservationDate not found - trying simpler match")
    # Try to find just the signature
    idx = c.find('  ReservationImageParseResult _normalizeReservationDate(ReservationImageParseResult result) {')
    idx2 = c.find('  ReservationImageParseResult _normalizeReservationDate(ReservationImageParseResult result) {', idx + 10)
    if idx2 > idx:
        print(f"  Found second at {idx2}, removing...")
        # Find end of this method
        brace_count = 0
        end_idx = idx2
        for i in range(idx2, len(c)):
            if c[i] == '{': brace_count += 1
            elif c[i] == '}':
                brace_count -= 1
                if brace_count == 0:
                    end_idx = i + 1
                    break
        c = c[:idx2] + c[end_idx:]
        print(f"  Removed {end_idx - idx2} chars")

# ===== Fix 3: Update original _maybeEnterReservationFlow to use conversation flow =====
old_maybe = '''  bool _maybeEnterReservationFlow(String text) {
    final String trimmed = text.trim();
    if (trimmed.isEmpty) return false;

    final ReservationImageParseResult result =
        ReservationImageParser.parse(trimmed);
    if (!_isReservationText(result)) return false;

    unawaited(_showReservationConfirm(_normalizeReservationDate(result)));
    return true;
  }'''

new_maybe = '''  bool _maybeEnterReservationFlow(String text) {
    final String trimmed = text.trim();
    if (trimmed.isEmpty) return false;

    final ReservationImageParseResult result =
        ReservationImageParser.parse(trimmed);
    if (!_isReservationText(result)) return false;

    _startReservationConversation(_normalizeReservationDate(result));
    return true;
  }'''

if old_maybe in c:
    c = c.replace(old_maybe, new_maybe, 1)
    print("Updated original _maybeEnterReservationFlow")
else:
    print("WARNING: original _maybeEnterReservationFlow not found")

# ===== Fix 4: Add onSuggestion parameter to _MessageBubble =====
old_mb = '''class _MessageBubble extends StatelessWidget {
  const _MessageBubble({required this.message, required this.themeColor});

  final _ChatMessage message;
  final Color themeColor;'''
new_mb = '''class _MessageBubble extends StatelessWidget {
  const _MessageBubble({required this.message, required this.themeColor, this.onSuggestion});

  final _ChatMessage message;
  final Color themeColor;
  final ValueChanged<String>? onSuggestion;'''
c = c.replace(old_mb, new_mb, 1)
print("Added onSuggestion to _MessageBubble")

# ===== Fix 5: Add reservationDraft to non-exhaustive switch statements =====
# Find the two switch(card.kind) blocks in _CardView._buildItems and _AgentCardDetailPage
# First, find them
for search in ['      case _CardKind.orderList:', '      case _CardKind.dishRank:']:
    idx = c.find(search)
    while idx >= 0:
        # Check if this is inside a switch that doesn't have reservationDraft yet
        context = c[idx:idx+500]
        if 'reservationDraft' not in context[:200]:
            # This switch needs the case added
            insert_pos = idx
            # Find the 'default:' in this switch
            default_idx = context.find('      default:')
            if default_idx >= 0:
                insert_pos = idx + default_idx
                # Insert before default
                c = c[:insert_pos] + "      case _CardKind.reservationDraft:\n        return Column(\n          children: card.items.map((Map<String, dynamic> item) {\n            return Padding(\n              padding: const EdgeInsets.symmetric(vertical: 2),\n              child: Row(\n                crossAxisAlignment: CrossAxisAlignment.start,\n                children: [\n                  Text('${item['label'] ?? ''}', style: const TextStyle(fontSize: 11, color: MyColours.color_999999)),\n                  const SizedBox(width: 10),\n                  Expanded(child: Text('${item['value'] ?? ''}', textAlign: TextAlign.right, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF303030)))),\n                ],\n              ),\n            );\n          }).toList(),\n        );\n" + c[insert_pos:]
                print(f"Added reservationDraft case at offset {insert_pos}")
        idx = c.find(search, idx + 1)

# ===== Fix 6: Pass onSuggestion from _send to _MessageBubble =====
# Find where _MessageBubble is instantiated
old_inst = '                            return _MessageBubble(\n                              message: _messages[index],\n                              themeColor: themeColor,\n                            );'
new_inst = '                            return _MessageBubble(\n                              message: _messages[index],\n                              themeColor: themeColor,\n                              onSuggestion: _send,\n                            );'
c = c.replace(old_inst, new_inst, 1)
print("Wired onSuggestion to _send")

# ===== Fix 7: _handleReservationClarification should handle all user messages with pending reservation =====
# Update _send to check and route to _handleReservationClarification
old_send = '''    if (_pendingReservation != null) {\n      _handleReservationClarification(text);\n      return;\n    }'''
# Check if this routing already exists
if '_pendingReservation' in c and '_handleReservationClarification' not in c[:2000]:
    print("Need to add routing for _handleReservationClarification")
    # Find the _send method and add the check
    send_idx = c.find('  void _send(String rawText) {')
    if send_idx >= 0:
        # Find the _maybeEnterReservationFlow check
        maybe_idx = c.find('if (_maybeEnterReservationFlow(text))', send_idx)
        if maybe_idx >= 0:
            # Insert before it
            insert_text = '''    if (_pendingReservation != null) {\n      _handleReservationClarification(text);\n      _inputController.clear();\n      FocusScope.of(context).unfocus();\n      return;\n    }\n\n    '''
            c = c[:maybe_idx] + insert_text + c[maybe_idx:]
            print("Added _handleReservationClarification routing to _send")

with open(PATH, 'w') as f:
    f.write(c)

print(f"\nDone. Lines: {c.count(chr(10))}")