import 'dart:async';

import 'package:flutter/foundation.dart';

import '../providers/kandang_provider.dart';
import '../providers/panen_provider.dart';
import '../providers/penjadwalan_provider.dart';
import 'panen_auto_capture_service.dart';

/// Scheduler ringan di level aplikasi untuk memicu panen otomatis pagi/sore.
///
/// Catatan: ini berjalan selama proses app masih hidup (foreground/background).
/// Jika proses dibunuh OS, trigger akan berhenti sampai app dibuka lagi.
class PanenRuntimeSchedulerService {
  PanenRuntimeSchedulerService._();

  static Timer? _timer;
  static bool _isRunning = false;
  static bool _isProcessing = false;
  static String? _lastPagiTriggerDate;
  static final Map<int, String> _lastSoreTriggerDateByIndex =
      {}; // Track per jadwal sore

  static Future<void> start({
    required PanenProvider panenProvider,
    required KandangProvider kandangProvider,
    required PenjadwalanProvider penjadwalanProvider,
  }) async {
    stop();

    _isRunning = true;
    _timer = Timer.periodic(const Duration(seconds: 30), (_) async {
      await _tick(
        panenProvider: panenProvider,
        kandangProvider: kandangProvider,
        penjadwalanProvider: penjadwalanProvider,
      );
    });

    await _tick(
      panenProvider: panenProvider,
      kandangProvider: kandangProvider,
      penjadwalanProvider: penjadwalanProvider,
    );

    if (kDebugMode) {
      print('✅ PanenRuntimeSchedulerService started (30s tick)');
    }
  }

  static void stop() {
    _isRunning = false;
    _timer?.cancel();
    _timer = null;
  }

  static Future<void> _tick({
    required PanenProvider panenProvider,
    required KandangProvider kandangProvider,
    required PenjadwalanProvider penjadwalanProvider,
  }) async {
    if (!_isRunning || _isProcessing) return;

    _isProcessing = true;
    try {
      final now = DateTime.now();
      final dateKey =
          '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}';

      final activeSchedules =
          penjadwalanProvider.penjadwalans.where((j) => j.aktif).toList();

      // Sort by ID urutan untuk memastikan penjadwalan1, penjadwalan2, dst
      activeSchedules.sort((a, b) {
        int numA = int.tryParse(a.id.replaceAll('penjadwalan', '')) ?? 999;
        int numB = int.tryParse(b.id.replaceAll('penjadwalan', '')) ?? 999;
        return numA.compareTo(numB);
      });

      int? morningHour;
      int? morningMinute;
      final afternoonSchedules = <(int index, int hour, int minute)>[];

      // Jadwal pertama (penjadwalan1) = PAGI
      // Jadwal ke-2+ (penjadwalan2, penjadwalan3, dst) = SORE
      for (int i = 0; i < activeSchedules.length; i++) {
        final schedule = activeSchedules[i];
        final parsed = _parseJam(schedule.jam);
        if (parsed == null) continue;

        final hour = parsed.$1;
        final minute = parsed.$2;

        if (i == 0) {
          // Jadwal pertama = PAGI
          morningHour = hour;
          morningMinute = minute;
        } else {
          // Jadwal ke-2+ = SORE (simpan semua jadwal sore)
          afternoonSchedules.add((i, hour, minute));
        }
      }

      // Trigger pagi hanya jika ada jadwal pagi yang aktif
      if (morningHour != null && morningMinute != null) {
        final morningStart = DateTime(
          now.year,
          now.month,
          now.day,
          morningHour,
          morningMinute,
        );
        final morningEnd = morningStart.add(const Duration(minutes: 10));
        final isMorningWindow =
            !now.isBefore(morningStart) && !now.isAfter(morningEnd);
        if (isMorningWindow && _lastPagiTriggerDate != dateKey) {
          if (kDebugMode) {
            print(
                '🕘 Trigger runtime panen pagi ($dateKey @ $morningHour:${morningMinute.toString().padLeft(2, '0')})');
          }
          await PanenAutoCaptureService.triggerMorningCapture(
            panenProvider,
            kandangProvider,
          );
          _lastPagiTriggerDate = dateKey;
        }
      }

      // Trigger semua jadwal sore yang waktunya match
      for (int schedIdx = 0; schedIdx < afternoonSchedules.length; schedIdx++) {
        final (index, afternoonHour, afternoonMinute) =
            afternoonSchedules[schedIdx];
        final isLastSchedule = schedIdx == afternoonSchedules.length - 1;

        final afternoonStart = DateTime(
          now.year,
          now.month,
          now.day,
          afternoonHour,
          afternoonMinute,
        );
        final afternoonEnd = afternoonStart.add(const Duration(minutes: 10));
        final isAfternoonWindow =
            !now.isBefore(afternoonStart) && !now.isAfter(afternoonEnd);

        final lastTriggerDate = _lastSoreTriggerDateByIndex[index];
        final shouldTrigger = isAfternoonWindow &&
            (lastTriggerDate == null || lastTriggerDate != dateKey);

        if (shouldTrigger) {
          if (kDebugMode) {
            print(
                '🕒 Trigger runtime panen sore #${index} ($dateKey @ $afternoonHour:${afternoonMinute.toString().padLeft(2, '0')})');
          }
          await PanenAutoCaptureService.triggerAfternoonCapture(
            panenProvider,
            kandangProvider,
            isLastSchedule: isLastSchedule,
          );
          _lastSoreTriggerDateByIndex[index] = dateKey;
        }
      }
    } catch (e) {
      if (kDebugMode) {
        print('❌ PanenRuntimeSchedulerService tick error: $e');
      }
    } finally {
      _isProcessing = false;
    }
  }

  static (int, int)? _parseJam(String jam) {
    final parts = jam.split(':');
    if (parts.length < 2) return null;
    final hour = int.tryParse(parts[0]);
    final minute = int.tryParse(parts[1]);
    if (hour == null || minute == null) return null;
    if (hour < 0 || hour > 23 || minute < 0 || minute > 59) return null;
    return (hour, minute);
  }
}
