part of 'main.dart';

class OtthonApp extends StatefulWidget {
  const OtthonApp({super.key});

  @override
  State<OtthonApp> createState() => _OtthonAppState();
}

class _OtthonAppState extends State<OtthonApp> {
  final store = AppJsonStore();
  final weatherService = WeatherService();
  List<Person> people = defaultPeople();
  List<GoogleCalendarConnection> googleConnections = defaultGoogleConnections();
  List<CalendarEvent> syncedEvents = [];
  List<String> todoSuggestions = [];
  JarvisSettings jarvisSettings = JarvisSettings.defaults();
  WeatherSnapshot? weather;
  String themeId = 'sage';
  bool loaded = false;

  AppThemeStyle get activeTheme => appThemes.firstWhere(
    (theme) => theme.id == themeId,
    orElse: () => appThemes.first,
  );

  @override
  void initState() {
    super.initState();
    _loadSettings();
    _loadWeather();
  }

  Future<void> _loadSettings() async {
    final settings = await store.load();
    if (!mounted) return;
    setState(() {
      people = settings.people;
      googleConnections = settings.googleConnections;
      syncedEvents = settings.syncedEvents;
      todoSuggestions = settings.todoSuggestions;
      jarvisSettings = settings.jarvisSettings;
      themeId = settings.themeId;
      loaded = true;
    });
  }

  Future<void> _saveSettings() async {
    await store.save(
      AppSettings(
        people: people,
        themeId: themeId,
        googleConnections: googleConnections,
        syncedEvents: syncedEvents,
        todoSuggestions: todoSuggestions,
        jarvisSettings: jarvisSettings,
      ),
    );
  }

  void _updatePeople(List<Person> nextPeople) {
    setState(() => people = nextPeople);
    _saveSettings();
  }

  void _updateTheme(String nextThemeId) {
    setState(() => themeId = nextThemeId);
    _saveSettings();
  }

  void _updateGoogleConnections(
    List<GoogleCalendarConnection> nextConnections,
  ) {
    setState(() => googleConnections = nextConnections);
    _saveSettings();
  }

  void _updateSyncedEvents(List<CalendarEvent> nextEvents) {
    setState(() => syncedEvents = nextEvents);
    _saveSettings();
  }

  void _updateTodoSuggestions(List<String> nextSuggestions) {
    setState(() => todoSuggestions = nextSuggestions);
    _saveSettings();
  }

  void _updateJarvisSettings(JarvisSettings nextSettings) {
    setState(() => jarvisSettings = nextSettings);
    _saveSettings();
  }

  Future<void> _loadWeather() async {
    final snapshot = await weatherService.loadCurrentWeather();
    if (!mounted) return;
    setState(() => weather = snapshot);
  }

  @override
  Widget build(BuildContext context) {
    final theme = activeTheme;
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'K\u00f6z\u00f6sT\u00e9r',
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: theme.seed,
          surface: theme.surface,
        ),
        scaffoldBackgroundColor: theme.surface,
        fontFamily: 'Arial',
        cardTheme: const CardThemeData(
          elevation: 0,
          color: Colors.white,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(20)),
          ),
        ),
        inputDecorationTheme: InputDecorationTheme(
          filled: true,
          fillColor: const Color(0xFFF1F3EF),
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(14),
            borderSide: BorderSide.none,
          ),
        ),
      ),
      home: HomeShell(
        people: people,
        googleConnections: googleConnections,
        syncedEvents: syncedEvents,
        todoSuggestions: todoSuggestions,
        jarvisSettings: jarvisSettings,
        weather: weather,
        themeId: themeId,
        loaded: loaded,
        onPeopleChanged: _updatePeople,
        onThemeChanged: _updateTheme,
        onGoogleConnectionsChanged: _updateGoogleConnections,
        onSyncedEventsChanged: _updateSyncedEvents,
        onTodoSuggestionsChanged: _updateTodoSuggestions,
        onJarvisSettingsChanged: _updateJarvisSettings,
      ),
    );
  }
}

class HomeShell extends StatefulWidget {
  const HomeShell({
    super.key,
    required this.people,
    required this.googleConnections,
    required this.syncedEvents,
    required this.todoSuggestions,
    required this.jarvisSettings,
    required this.weather,
    required this.themeId,
    required this.loaded,
    required this.onPeopleChanged,
    required this.onThemeChanged,
    required this.onGoogleConnectionsChanged,
    required this.onSyncedEventsChanged,
    required this.onTodoSuggestionsChanged,
    required this.onJarvisSettingsChanged,
  });

  final List<Person> people;
  final List<GoogleCalendarConnection> googleConnections;
  final List<CalendarEvent> syncedEvents;
  final List<String> todoSuggestions;
  final JarvisSettings jarvisSettings;
  final WeatherSnapshot? weather;
  final String themeId;
  final bool loaded;
  final ValueChanged<List<Person>> onPeopleChanged;
  final ValueChanged<String> onThemeChanged;
  final ValueChanged<List<GoogleCalendarConnection>> onGoogleConnectionsChanged;
  final ValueChanged<List<CalendarEvent>> onSyncedEventsChanged;
  final ValueChanged<List<String>> onTodoSuggestionsChanged;
  final ValueChanged<JarvisSettings> onJarvisSettingsChanged;

  @override
  State<HomeShell> createState() => _HomeShellState();
}

class _HomeShellState extends State<HomeShell> {
  int selected = 0;
  bool jarvisBackendOnline = false;
  Timer? jarvisBackendTimer;

  @override
  void initState() {
    super.initState();
    _checkJarvisBackend();
    jarvisBackendTimer = Timer.periodic(
      const Duration(seconds: 15),
      (_) => _checkJarvisBackend(),
    );
  }

  @override
  void dispose() {
    jarvisBackendTimer?.cancel();
    super.dispose();
  }

  final events = <CalendarEvent>[
    CalendarEvent(
      'Csal\u00e1di reggeli',
      '07:30',
      '08:15',
      const Color(0xFF79A894),
      date: DateTime(2026, 7, 20),
    ),
    CalendarEvent(
      'Csapatmegbesz\u00e9l\u00e9s',
      '10:00',
      '11:00',
      const Color(0xFF7189C8),
      date: DateTime(2026, 7, 20),
      place: 'Google Meet',
    ),
    CalendarEvent(
      'Fogorvos',
      '16:30',
      '17:15',
      const Color(0xFFE89552),
      date: DateTime(2026, 7, 21),
      place: 'R\u00f3zsadomb',
    ),
    CalendarEvent(
      'Farsang',
      '10:00',
      '12:00',
      const Color(0xFF7189C8),
      date: DateTime(2026, 7, 22),
      personId: 'balint',
    ),
    CalendarEvent(
      'Vacsora Ann\u00e1\u00e9kkal',
      '19:00',
      '21:30',
      const Color(0xFF9B78B4),
      date: DateTime(2026, 7, 24),
      place: 'Kert Bisztr\u00f3',
    ),
    CalendarEvent(
      'Piac',
      '09:00',
      '10:30',
      const Color(0xFF79A894),
      date: DateTime(2026, 7, 25),
    ),
    CalendarEvent(
      'Ballag\u00e1s',
      '09:00',
      '11:00',
      const Color(0xFFE89552),
      date: DateTime(2026, 8, 1),
      personId: 'emilia',
    ),
  ];

  final shopping = <ShoppingItem>[
    ShoppingItem('Zabtej', '2 doboz', 'Tejterm\u00e9k'),
    ShoppingItem('Paradicsom', '1 kg', 'Z\u00f6lds\u00e9g'),
    ShoppingItem('Kov\u00e1szos keny\u00e9r', '1 db', 'P\u00e9k\u00e1ru'),
    ShoppingItem(
      'Mosogat\u00f3g\u00e9p tabletta',
      '1 csomag',
      'H\u00e1ztart\u00e1s',
    ),
    ShoppingItem('Ban\u00e1n', '6 db', 'Gy\u00fcm\u00f6lcs', done: true),
  ];

  final stock = <StockItem>[
    StockItem('Toj\u00e1s', 8, 'db', 'H\u0171t\u0151', 'j\u00fal. 24.'),
    StockItem(
      'G\u00f6r\u00f6g joghurt',
      2,
      'db',
      'H\u0171t\u0151',
      'j\u00fal. 22.',
    ),
    StockItem('Vaj', 1, 'csomag', 'H\u0171t\u0151', 'j\u00fal. 29.'),
    StockItem('Rizs', 2, 'kg', 'Kamra', '2027. m\u00e1rc.'),
    StockItem('T\u00e9szta', 3, 'csomag', 'Kamra', '2027. jan.'),
    StockItem('K\u00e1v\u00e9', 1, 'csomag', 'Kamra', '2026. nov.'),
  ];

  List<CalendarEvent> get allEvents => [...events, ...widget.syncedEvents];

  final labels = const [
    'Napt\u00e1r',
    'Bev\u00e1s\u00e1rl\u00e1s',
    'K\u00e9szlet',
    'Csal\u00e1dtagok',
    'St\u00edlus',
    'Fi\u00f3kok',
  ];

  final icons = const [
    Icons.calendar_month_rounded,
    Icons.shopping_basket_outlined,
    Icons.kitchen_outlined,
    Icons.group_outlined,
    Icons.palette_outlined,
    Icons.sync_rounded,
  ];

  @override
  Widget build(BuildContext context) {
    final wide = MediaQuery.sizeOf(context).width >= 850;
    final body = IndexedStack(
      index: selected,
      children: [
        CalendarPage(
          events: allEvents,
          people: widget.people,
          weather: widget.weather,
          onAdd: _addEvent,
          onEdit: _editEvent,
          onAssignPerson: _assignSyncedEventToPerson,
        ),
        ShoppingPage(
          items: shopping,
          onChanged: () => setState(() {}),
          onAdd: _addShopping,
        ),
        StockPage(
          items: stock,
          onChanged: () => setState(() {}),
          onAdd: _addStock,
          onEdit: _editStock,
          jarvisSettings: widget.jarvisSettings,
        ),
        PersonsPage(
          people: widget.people,
          events: allEvents,
          onAdd: _addPerson,
          onEdit: _editPerson,
          onDelete: _deletePerson,
        ),
        StylePage(
          themeId: widget.themeId,
          onThemeChanged: widget.onThemeChanged,
        ),
        AccountsPage(
          connections: widget.googleConnections,
          cachedEvents: widget.syncedEvents,
          people: widget.people,
          onChanged: widget.onGoogleConnectionsChanged,
          onSyncedEventsChanged: widget.onSyncedEventsChanged,
        ),
      ],
    );

    return Scaffold(
      body: SafeArea(
        child: Row(
          children: [
            if (wide)
              SizedBox(
                width: 220,
                child: Stack(
                  children: [
                    NavigationRail(
                      backgroundColor: Colors.white,
                      extended: true,
                      minExtendedWidth: 220,
                      selectedIndex: selected,
                      onDestinationSelected: (i) =>
                          setState(() => selected = i),
                      leading: Padding(
                        padding: const EdgeInsets.fromLTRB(12, 16, 12, 28),
                        child: Container(
                          padding: const EdgeInsets.all(10),
                          decoration: BoxDecoration(
                            color: const Color(0xFFF6F4EF),
                            borderRadius: BorderRadius.circular(20),
                            border: Border.all(
                              color: sage.withValues(alpha: .10),
                            ),
                            boxShadow: [
                              BoxShadow(
                                color: sage.withValues(alpha: .08),
                                blurRadius: 18,
                                offset: const Offset(0, 10),
                              ),
                            ],
                          ),
                          child: Row(
                            children: [
                              Container(
                                width: 42,
                                height: 42,
                                decoration: BoxDecoration(
                                  color: sage,
                                  borderRadius: BorderRadius.circular(15),
                                ),
                                clipBehavior: Clip.antiAlias,
                                child: const Icon(
                                  Icons.dashboard_customize_outlined,
                                  color: Colors.white,
                                  size: 24,
                                ),
                              ),
                              const SizedBox(width: 10),
                              Expanded(
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  mainAxisSize: MainAxisSize.min,
                                  children: [
                                    const Text(
                                      'K\u00f6z\u00f6sT\u00e9r',
                                      maxLines: 1,
                                      overflow: TextOverflow.ellipsis,
                                      style: TextStyle(
                                        fontSize: 18,
                                        fontWeight: FontWeight.w900,
                                        color: ink,
                                        letterSpacing: .2,
                                      ),
                                    ),
                                    Text(
                                      widget.loaded
                                          ? 'Tervez\u0151'
                                          : 'JSON bet\u00f6lt\u00e9se\u2026',
                                      style: const TextStyle(
                                        fontSize: 11,
                                        color: Colors.black45,
                                        fontWeight: FontWeight.w800,
                                      ),
                                    ),
                                    const SizedBox(height: 2),
                                    const Text(
                                      appVersionLabel,
                                      style: TextStyle(
                                        fontSize: 10,
                                        color: Colors.black38,
                                        fontWeight: FontWeight.w800,
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                              IconButton(
                                tooltip: 'JARVIS be\u00e1ll\u00edt\u00e1sok',
                                onPressed: _openJarvisSettings,
                                icon: const Icon(
                                  Icons.settings_outlined,
                                  size: 20,
                                ),
                                style: IconButton.styleFrom(
                                  backgroundColor: Colors.white,
                                  foregroundColor: sage,
                                  minimumSize: const Size(36, 36),
                                  tapTargetSize:
                                      MaterialTapTargetSize.shrinkWrap,
                                  padding: EdgeInsets.zero,
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                      destinations: List.generate(
                        labels.length,
                        (i) => NavigationRailDestination(
                          icon: Icon(icons[i]),
                          selectedIcon: Icon(icons[i]),
                          label: Text(labels[i]),
                        ),
                      ),
                    ),
                    Positioned(
                      left: 16,
                      bottom: 12,
                      right: 16,
                      child: Container(
                        padding: const EdgeInsets.all(10),
                        decoration: BoxDecoration(
                          color: Colors.black.withValues(alpha: .92),
                          borderRadius: BorderRadius.circular(18),
                          border: Border.all(
                            color: Colors.white.withValues(alpha: .08),
                          ),
                          boxShadow: [
                            BoxShadow(
                              color: Colors.black.withValues(alpha: .08),
                              blurRadius: 18,
                              offset: const Offset(0, 10),
                            ),
                          ],
                        ),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            Row(
                              children: [
                                Container(
                                  width: 27,
                                  height: 27,
                                  decoration: BoxDecoration(
                                    color: Colors.white.withValues(alpha: .08),
                                    borderRadius: BorderRadius.circular(10),
                                  ),
                                  clipBehavior: Clip.antiAlias,
                                  child: Image.asset(
                                    'assets/branding/jarvis-api-logo.png',
                                    fit: BoxFit.cover,
                                  ),
                                ),
                                const SizedBox(width: 8),
                                const Expanded(
                                  child: Text(
                                    'JARVIS Backend',
                                    maxLines: 1,
                                    overflow: TextOverflow.ellipsis,
                                    style: TextStyle(
                                      color: Colors.white,
                                      fontSize: 11,
                                      fontWeight: FontWeight.w900,
                                    ),
                                  ),
                                ),
                              ],
                            ),
                            const SizedBox(height: 8),
                            Center(
                              child: Column(
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  Container(
                                    width: 11,
                                    height: 11,
                                    decoration: BoxDecoration(
                                      color: jarvisBackendOnline
                                          ? Colors.greenAccent
                                          : Colors.redAccent,
                                      shape: BoxShape.circle,
                                      boxShadow: [
                                        BoxShadow(
                                          color:
                                              (jarvisBackendOnline
                                                      ? Colors.greenAccent
                                                      : Colors.redAccent)
                                                  .withValues(alpha: .45),
                                          blurRadius: 8,
                                        ),
                                      ],
                                    ),
                                  ),
                                  const SizedBox(height: 4),
                                  Text(
                                    jarvisBackendOnline ? 'online' : 'offline',
                                    style: TextStyle(
                                      color: jarvisBackendOnline
                                          ? Colors.greenAccent
                                          : Colors.redAccent,
                                      fontSize: 10,
                                      fontWeight: FontWeight.w800,
                                    ),
                                  ),
                                ],
                              ),
                            ),
                            const SizedBox(height: 10),
                            Center(
                              child: Opacity(
                                opacity: .78,
                                child: Image.asset(
                                  'assets/branding/abdai-design-logo.png',
                                  fit: BoxFit.contain,
                                  alignment: Alignment.center,
                                  height: 28,
                                ),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            Expanded(child: body),
          ],
        ),
      ),
      bottomNavigationBar: wide
          ? null
          : NavigationBar(
              selectedIndex: selected,
              onDestinationSelected: (i) => setState(() => selected = i),
              destinations: List.generate(
                labels.length,
                (i) => NavigationDestination(
                  icon: Icon(icons[i]),
                  label: labels[i],
                ),
              ),
            ),
    );
  }

  Future<void> _checkJarvisBackend() async {
    final online = await _isJarvisBackendOnline();
    if (!mounted || jarvisBackendOnline == online) return;
    setState(() => jarvisBackendOnline = online);
  }

  Future<bool> _isJarvisBackendOnline() async {
    try {
      final baseUri = Uri.parse(
        normalizeJarvisUrl(widget.jarvisSettings.apiUrl),
      );
      final response = await http
          .get(baseUri.resolve('/health'))
          .timeout(const Duration(seconds: 3));
      return response.statusCode >= 200 && response.statusCode < 300;
    } catch (_) {
      return false;
    }
  }

  Future<void> _openJarvisSettings() async {
    final result = await showDialog<JarvisSettings>(
      context: context,
      builder: (_) => JarvisSettingsDialog(
        settings: widget.jarvisSettings,
        onRegister: _registerJarvisDevice,
        onRefreshStatus: _refreshJarvisDeviceStatus,
      ),
    );
    if (result == null) return;
    widget.onJarvisSettingsChanged(result);
    await Future<void>.delayed(Duration.zero);
    _checkJarvisBackend();
  }

  Future<JarvisSettings> _registerJarvisDevice(
    JarvisSettings settings,
    String deviceName,
  ) async {
    final baseUri = Uri.parse(normalizeJarvisUrl(settings.apiUrl));
    final trimmedDeviceName = deviceName.trim().isEmpty
        ? 'Family tablet'
        : deviceName.trim();
    final response = await http
        .post(
          baseUri.resolve('/api/devices/register'),
          headers: {
            'Content-Type': 'application/json',
            'X-Otthon-Token': settings.apiToken,
          },
          body: jsonEncode({
            'deviceName': trimmedDeviceName,
            'platform': Platform.operatingSystem,
          }),
        )
        .timeout(const Duration(seconds: 12));

    if (response.statusCode < 200 || response.statusCode >= 300) {
      throw Exception('JARVIS registration failed: ${response.statusCode}');
    }

    final payload = jsonDecode(response.body);
    if (payload is! Map<String, dynamic>) {
      throw Exception('Invalid JARVIS response.');
    }

    return settings.copyWith(
      deviceName: trimmedDeviceName,
      deviceId: payload['id'] as int?,
      deviceToken: payload['deviceToken'] as String?,
      registrationStatus: payload['status'] as String? ?? 'pending',
    );
  }

  Future<JarvisSettings> _refreshJarvisDeviceStatus(
    JarvisSettings settings,
  ) async {
    final deviceId = settings.deviceId;
    if (deviceId == null) {
      throw Exception('Nincs regisztr\u00e1lt eszk\u00f6z.');
    }

    final baseUri = Uri.parse(normalizeJarvisUrl(settings.apiUrl));
    final response = await http
        .get(
          baseUri.resolve('/api/devices/$deviceId/status'),
          headers: {'X-Otthon-Token': settings.apiToken},
        )
        .timeout(const Duration(seconds: 8));

    if (response.statusCode < 200 || response.statusCode >= 300) {
      throw Exception('JARVIS status failed: ${response.statusCode}');
    }

    final payload = jsonDecode(response.body);
    if (payload is! Map<String, dynamic>) {
      throw Exception('Invalid JARVIS response.');
    }

    if (payload['found'] == false ||
        payload['status'] == 'notRegistered' ||
        payload['status'] == 'notFound') {
      return settings.copyWith(clearDevice: true);
    }

    return settings.copyWith(
      registrationStatus: payload['status'] as String? ?? 'pending',
    );
  }

  Future<void> _addEvent() async {
    final data = await showDialog<EventInput>(
      context: context,
      builder: (_) => EventAddDialog(
        people: widget.people,
        todoSuggestions: widget.todoSuggestions,
      ),
    );
    if (data != null && data.title.trim().isNotEmpty) {
      final assignedPersonId = data.personId ?? everyonePersonId;
      setState(
        () => events.add(
          CalendarEvent(
            data.title.trim(),
            data.start.isEmpty ? '12:00' : data.start,
            '13:00',
            assignedPersonId == everyonePersonId
                ? sage
                : widget.people
                      .firstWhere((p) => p.id == assignedPersonId)
                      .color,
            personId: assignedPersonId,
            date: data.date,
            note: data.note,
            hasTodos: data.hasTodos,
            todos: data.todos,
          ),
        ),
      );
      _rememberTodos(data.todos);
    }
  }

  Future<void> _editEvent(CalendarEvent event) async {
    final data = await showDialog<EventInput>(
      context: context,
      builder: (_) => EventAddDialog(
        people: widget.people,
        event: event,
        todoSuggestions: widget.todoSuggestions,
      ),
    );
    if (data == null || data.title.trim().isEmpty) return;

    final assignedPersonId = data.personId ?? everyonePersonId;
    final color = assignedPersonId == everyonePersonId
        ? sage
        : widget.people.firstWhere((p) => p.id == assignedPersonId).color;
    final updated = event.copyWith(
      title: data.title.trim(),
      start: data.start.isEmpty ? '12:00' : data.start,
      date: data.date,
      color: color,
      personId: assignedPersonId,
      note: data.note,
      hasTodos: data.hasTodos,
      todos: data.todos,
    );

    setState(() {
      for (var i = 0; i < events.length; i++) {
        if (identical(events[i], event)) {
          events[i] = updated;
          return;
        }
      }
    });

    if (event.isSynced) {
      final nextSyncedEvents = [
        for (final syncedEvent in widget.syncedEvents)
          if (identical(syncedEvent, event)) updated else syncedEvent,
      ];
      widget.onSyncedEventsChanged(nextSyncedEvents);
    }
    _rememberTodos(data.todos);
  }

  void _rememberTodos(List<String> todos) {
    final nextSuggestions = [
      ...widget.todoSuggestions,
      ...todos.where((todo) => todo.trim().isNotEmpty),
    ].map((todo) => todo.trim()).toSet().toList()..sort();
    widget.onTodoSuggestionsChanged(nextSuggestions);
  }

  Future<void> _addPerson() async {
    final draft = await showDialog<PersonDraft>(
      context: context,
      builder: (_) => PersonDialog(
        title: '\u00daj csal\u00e1dtag',
        initialColor: personColors[widget.people.length % personColors.length],
        initialAvatar:
            avatarPresets[widget.people.length % avatarPresets.length].symbol,
      ),
    );
    if (draft == null) return;

    widget.onPeopleChanged([
      ...widget.people,
      Person(
        id: uniqueId(),
        name: draft.name,
        colorValue: draft.color.toARGB32(),
        avatar: draft.avatar,
        nextEventLimit: draft.nextEventLimit,
      ),
    ]);
  }

  Future<void> _editPerson(Person person) async {
    final draft = await showDialog<PersonDraft>(
      context: context,
      builder: (_) => PersonDialog(
        title: '${person.name} szerkeszt\u00e9se',
        initialName: person.name,
        initialColor: person.color,
        initialAvatar: person.avatar,
        initialNextEventLimit: person.nextEventLimit,
      ),
    );
    if (draft == null) return;

    widget.onPeopleChanged(
      widget.people
          .map(
            (item) => item.id == person.id
                ? item.copyWith(
                    name: draft.name,
                    colorValue: draft.color.toARGB32(),
                    avatar: draft.avatar,
                    nextEventLimit: draft.nextEventLimit,
                  )
                : item,
          )
          .toList(),
    );
  }

  Future<void> _deletePerson(Person person) async {
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('${person.name} t\u00f6rl\u00e9se?'),
        content: const Text(
          'A csal\u00e1dtag t\u00f6rl\u0151dik a JSON-b\u0151l. A hozz\u00e1 k\u00f6t\u00f6tt esem\u00e9nyek megmaradnak, de "Mindenki" esem\u00e9nny\u00e9 v\u00e1lnak.',
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context, false),
            child: const Text('M\u00e9gse'),
          ),
          FilledButton(
            onPressed: () => Navigator.pop(context, true),
            child: const Text('T\u00f6rl\u00e9s'),
          ),
        ],
      ),
    );
    if (confirmed != true) return;

    setState(() {
      for (var i = 0; i < events.length; i++) {
        if (events[i].personId == person.id) {
          events[i] = events[i].copyWith(clearPerson: true);
        }
      }
    });
    widget.onPeopleChanged(
      widget.people.where((item) => item.id != person.id).toList(),
    );
  }

  void _assignSyncedEventToPerson(CalendarEvent event, Person person) {
    final nextSyncedEvents = widget.syncedEvents
        .map(
          (item) => sameImportedEvent(item, event)
              ? item.copyWith(personId: person.id)
              : item,
        )
        .toList();
    widget.onSyncedEventsChanged(nextSyncedEvents);
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('${event.title} hozz\u00e1rendelve: ${person.name}'),
      ),
    );
  }

  Future<void> _addShopping() async {
    final data = await showDialog<List<String>>(
      context: context,
      builder: (_) => const QuickAddDialog(
        title: 'T\u00e9tel hozz\u00e1ad\u00e1sa',
        firstLabel: 'Mit vegy\u00fcnk?',
        secondLabel: 'Mennyis\u00e9g',
      ),
    );
    if (data != null && data[0].trim().isNotEmpty) {
      setState(
        () => shopping.add(
          ShoppingItem(
            data[0],
            data[1].isEmpty ? '1 db' : data[1],
            'Egy\u00e9b',
          ),
        ),
      );
    }
  }

  Future<void> _addStock() async {
    final data = await showDialog<StockInput>(
      context: context,
      builder: (_) => StockAddDialog(jarvisSettings: widget.jarvisSettings),
    );
    if (data != null && data.name.trim().isNotEmpty) {
      setState(
        () => stock.add(
          StockItem(
            data.name,
            data.amount,
            data.unit,
            data.location,
            data.expiry,
          ),
        ),
      );
      unawaited(_sendFoodLearningEvent(data, action: 'stock-added'));
    }
  }

  Future<void> _editStock(StockItem item) async {
    final data = await showDialog<StockInput>(
      context: context,
      builder: (_) => StockAddDialog(
        jarvisSettings: widget.jarvisSettings,
        initialItem: item,
      ),
    );
    if (data == null || data.name.trim().isEmpty) return;

    setState(() {
      item.name = data.name.trim();
      item.amount = data.amount;
      item.unit = data.unit.trim().isEmpty ? 'db' : data.unit.trim();
      item.location = data.location;
      item.expiry = data.expiry.trim().isEmpty
          ? 'nincs megadva'
          : data.expiry.trim();
    });
    unawaited(_sendFoodLearningEvent(data, action: 'stock-updated'));
  }

  Future<void> _sendFoodLearningEvent(
    StockInput input, {
    required String action,
  }) async {
    final apiUrl = widget.jarvisSettings.apiUrl.trim();
    final apiToken = widget.jarvisSettings.apiToken.trim();
    if (apiUrl.isEmpty || apiToken.isEmpty) return;

    try {
      final baseUri = Uri.parse(normalizeJarvisUrl(apiUrl));
      await http
          .post(
            baseUri.resolve('/api/food-events'),
            headers: {
              'Content-Type': 'application/json',
              'X-Otthon-Token': apiToken,
            },
            body: jsonEncode({
              'productName': input.name.trim(),
              'barcode': input.barcode.trim().isEmpty
                  ? null
                  : input.barcode.trim(),
              'action': action,
              'amount': input.amount,
              'unit': input.unit,
              'location': input.location,
              'localTime': DateTime.now().toIso8601String(),
            }),
          )
          .timeout(const Duration(seconds: 8));
    } catch (_) {
      // A tanul\u00e1s kieg\u00e9sz\u00edt\u0151 funkci\u00f3: offline/hiba eset\u00e9n a k\u00e9szlet ment\u00e9se nem akad meg.
    }
  }
}
