import 'package:cupang_app/models/FirebaseData.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:intl/intl.dart'; // Import package intl
import 'package:toast/toast.dart';
import 'mqtt_service.dart'; // Import MQTT service
import 'package:flutter/services.dart'; // Import for ToastContext
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert'; // For json encoding/decoding

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: const ColorScheme.light(background: Colors.white),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
      debugShowCheckedModeBanner: false,
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String? pagi;
  String? siang;
  String? malam;
  int pagiPutaran = 0;
  int siangPutaran = 0;
  int malamPutaran = 0;
  TimeOfDay _timeOfDay = TimeOfDay.now();
  late MQTTService mqttService;
  List<Map<String, dynamic>> feedingHistory = [];

  @override
  void initState() {
    super.initState();
    _loadFeedingHistory();
    mqttService = MQTTService();
    mqttService.initializeMQTT();
    reload(); // Load data when widget is first initialized
  }

  @override
  Widget build(BuildContext context) {
    ToastContext().init(context);
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.blue.shade900,
        title: const Text(
          'PiCo',
          style: TextStyle(color: Colors.white),
        ),
        centerTitle: true,
        actions: [
          IconButton(
            icon: Icon(Icons.history),
            onPressed: _showFeedingHistory,
          ),
        ],
      ),
      body: Column(
        children: [
          const SizedBox(height: 10),
          buildScheduleCard('Pagi', pagi, pagiPutaran, _setPagi),
          buildScheduleCard('Siang', siang, siangPutaran, _setSiang),
          buildScheduleCard('Malam', malam, malamPutaran, _setMalam),
        ],
      ),
      floatingActionButton: Padding(
        padding: const EdgeInsets.only(bottom: 30.0),
        child: FloatingActionButton.extended(
          onPressed: _manualFeed,
          label: const Text('Pakan Manual'),
          backgroundColor: Colors.blue, // Change background color as needed
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    );
  }

  Widget buildScheduleCard(
      String title, String? time, int putaran, Function setFunction) {
    return Container(
      height: 100,
      margin: const EdgeInsets.all(10),
      decoration: const BoxDecoration(
        color: Colors.blue,
        borderRadius: BorderRadius.all(Radius.circular(10)),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Padding(
              padding: const EdgeInsets.only(left: 20),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  if (time != null)
                    Text(
                      time,
                      style: const TextStyle(
                        color: Colors.white,
                        fontSize: 27,
                      ),
                    )
                  else
                    const CircularProgressIndicator(color: Colors.white),
                  Text(
                    title,
                    style: const TextStyle(
                      color: Colors.white,
                      fontSize: 14,
                    ),
                  ),
                  Text(
                    'Putaran: $putaran',
                    style: const TextStyle(
                      color: Colors.white,
                      fontSize: 14,
                    ),
                  ),
                ],
              )),
          Padding(
            padding: const EdgeInsets.only(right: 20),
            child: ElevatedButton(
              onPressed: () => setFunction(),
              child: const Text('Set', style: TextStyle(color: Colors.black)),
              style: ElevatedButton.styleFrom(backgroundColor: Colors.white),
            ),
          ),
        ],
      ),
    );
  }

  Future<void> _loadFeedingHistory() async {
    final prefs = await SharedPreferences.getInstance();
    final String? historyString = prefs.getString('feedingHistory');
    if (historyString != null) {
      setState(() {
        feedingHistory =
            List<Map<String, dynamic>>.from(json.decode(historyString));
      });
    }
  }

  Future<void> _saveFeedingHistory(Map<String, dynamic> record) async {
    final prefs = await SharedPreferences.getInstance();

    // Format tanggal dan waktu
    final formattedDate = DateFormat('yyyy-MM-dd').format(DateTime.now());
    record['tanggal'] =
        formattedDate; // Tambahkan tanggal dengan format yang diinginkan

    // Tambahkan riwayat baru di awal list
    feedingHistory.insert(0, record);
    if (feedingHistory.length > 10) {
      feedingHistory.removeLast(); // Hapus item paling lama jika melebihi 10
    }
    await prefs.setString('feedingHistory', json.encode(feedingHistory));
  }

  Future<void> _showFeedingHistory() async {
    await _loadFeedingHistory();
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Riwayat Pemberian Pakan'),
          content: SizedBox(
            width: double.maxFinite,
            child: ListView.builder(
              shrinkWrap: true,
              itemCount: feedingHistory.length,
              itemBuilder: (BuildContext context, int index) {
                final record = feedingHistory[index];
                return ListTile(
                  title: Text(record['time']),
                  subtitle: Text(
                      'Putaran: ${record['putaran']}, Tanggal: ${record['tanggal']}'),
                );
              },
            ),
          ),
          actions: <Widget>[
            TextButton(
              child: Text('OK'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  Future<void> _setPagi() async {
    TimeOfDay? picked = await showTimePicker(
      context: context,
      initialTime: _timeOfDay,
    );

    if (picked != null) {
      // Validasi waktu yang dipilih
      if (!isTimeInPagiRange(picked)) {
        // Gunakan Builder widget untuk mendapatkan BuildContext
        showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text('Pilih waktu antara 03:00 hingga 10.59 untuk pagi'),
              actions: <Widget>[
                TextButton(
                  child: Text('OK'),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          },
        );
        return;
      }

      String jam =
          '${picked.hour.toString().padLeft(2, '0')}:${picked.minute.toString().padLeft(2, '0')}';
      int putaran = await _showPutaranDialog();
      showLoadingDialog(context);
      // Update data di Firebase
      await FirebaseData(pagi: jam, pagiPutaran: putaran).toJson();
      Navigator.of(context).pop();

      // Tampilkan toast ketika waktu pakan otomatis telah tiba
      scheduleNotification(picked,
          const Duration(seconds: 5)); // Notifikasi 5 detik lebih lambat

      reload();
    }
  }

  bool isTimeInPagiRange(TimeOfDay time) {
    // Rentang waktu pagi adalah dari jam 03:00 hingga 10:59
    return time.hour >= 3 && time.hour < 11;
  }

  Future<void> _setSiang() async {
    TimeOfDay? picked = await showTimePicker(
      context: context,
      initialTime: _timeOfDay,
    );

    if (picked != null) {
      // Validasi waktu yang dipilih
      if (!isTimeInSiangRange(picked)) {
        // Gunakan Builder widget untuk mendapatkan BuildContext
        showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text('Pilih waktu antara 11:00 hingga 15:59 untuk siang'),
              actions: <Widget>[
                TextButton(
                  child: Text('OK'),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          },
        );
        return;
      }

      String jam =
          '${picked.hour.toString().padLeft(2, '0')}:${picked.minute.toString().padLeft(2, '0')}';
      int putaran = await _showPutaranDialog();
      showLoadingDialog(context);

      // Update data di Firebase
      await FirebaseData(siang: jam, siangPutaran: putaran).toJson();
      Navigator.of(context).pop();

      // Tampilkan toast ketika waktu pakan otomatis telah tiba
      scheduleNotification(picked,
          const Duration(seconds: 5)); // Notifikasi 5 detik lebih lambat

      reload();
    }
  }

  bool isTimeInSiangRange(TimeOfDay time) {
    // Rentang waktu siang adalah dari jam 11:00 hingga 15:59
    return time.hour >= 11 && time.hour < 16;
  }

  Future<void> _setMalam() async {
    TimeOfDay? picked = await showTimePicker(
      context: context,
      initialTime: _timeOfDay,
    );

    if (picked != null) {
      // Validasi waktu yang dipilih
      if (!isTimeInMalamRange(picked)) {
        // Gunakan Builder widget untuk mendapatkan BuildContext
        showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text('Pilih waktu antara 16:00 hingga 02:59 untuk malam'),
              actions: <Widget>[
                TextButton(
                  child: Text('OK'),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          },
        );
        return;
      }

      String jam =
          '${picked.hour.toString().padLeft(2, '0')}:${picked.minute.toString().padLeft(2, '0')}';
      int putaran = await _showPutaranDialog();
      showLoadingDialog(context);

      // Update data di Firebase
      await FirebaseData(malam: jam, malamPutaran: putaran).toJson();
      Navigator.of(context).pop();

      // Tampilkan toast ketika waktu pakan otomatis telah tiba
      scheduleNotification(picked,
          const Duration(seconds: 5)); // Notifikasi 5 detik lebih lambat

      reload();
    }
  }

  bool isTimeInMalamRange(TimeOfDay time) {
    // Rentang waktu malam dari jam 16:00 hingga 23:59 dan dari 00:00 hingga 02:59
    return (time.hour >= 16 && time.hour <= 23) ||
        (time.hour >= 0 && time.hour < 3);
  }

  int getPutaranForTime(TimeOfDay time) {
    if (time.hour >= 3 && time.hour < 11) {
      return pagiPutaran;
    } else if (time.hour >= 11 && time.hour < 16) {
      return siangPutaran;
    } else {
      return malamPutaran;
    }
  }

  void scheduleNotification(TimeOfDay pickedTime, Duration delay) {
    final now = DateTime.now();
    final scheduledTime = DateTime(
        now.year, now.month, now.day, pickedTime.hour, pickedTime.minute);

    // Jika waktu terjadwal sudah lewat hari ini, pindahkan ke hari berikutnya
    if (scheduledTime.isBefore(now)) {
      scheduledTime.add(Duration(days: 1));
    }

    // Hitung durasi sampai notifikasi harus ditampilkan
    final timeUntilNotification = scheduledTime.difference(now);

    // Jika waktu notifikasi sudah lewat, jangan jadwalkan
    if (timeUntilNotification.isNegative) {
      // Misalnya, tampilkan pesan kesalahan atau tangani kasus ini sesuai kebutuhan
      print("Waktu jadwal pakan sudah lewat. Notifikasi tidak dijadwalkan.");
      return;
    }

    // Tambahkan delay untuk notifikasi
    Timer(timeUntilNotification + delay, () async {
      // Simpan riwayat pakan otomatis
      await _saveFeedingHistory({
        'time': pickedTime.format(context),
        'putaran': getPutaranForTime(pickedTime),
        // 'type': 'automatic' // Hapus field type
      });

      // Tampilkan notifikasi hanya setelah pakan benar-benar diberikan
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(
              'Pakan otomatis pada pukul ${pickedTime.format(context)} telah dilakukan'),
        ),
      );
    });
  }

  Future<void> reload() async {
    final jam = await FirebaseData().getData();
    setState(() {
      pagi = jam.pagi;
      siang = jam.siang;
      malam = jam.malam;
      pagiPutaran = jam.pagiPutaran ?? 0;
      siangPutaran = jam.siangPutaran ?? 0;
      malamPutaran = jam.malamPutaran ?? 0;
    });
    print([pagi, siang, malam, pagiPutaran, siangPutaran, malamPutaran]);
  }

  Future<int> _showPutaranDialog() async {
    int putaran = 0;
    await showDialog<int>(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Set Putaran Servo'),
          content: TextField(
            keyboardType: TextInputType.number,
            onChanged: (value) {
              putaran = int.tryParse(value) ?? 0;
            },
            decoration: InputDecoration(hintText: "Masukkan jumlah putaran"),
          ),
          actions: <Widget>[
            TextButton(
              child: Text('OK'),
              onPressed: () {
                Navigator.of(context).pop(putaran);
              },
            ),
          ],
        );
      },
    );
    return putaran;
  }

  Future<void> _manualFeed() async {
    final now = DateTime.now();
    final formattedTime =
        '${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}';
    showLoadingDialog(context);

    try {
      // Menghubungkan ke broker MQTT
      await mqttService.connect();
      // Mengirim pesan manual feed
      await mqttService.sendManualFeedMessage();

      // Tambahkan penundaan sementara (misalnya 5 detik) sebelum menampilkan notifikasi
      await Future.delayed(const Duration(seconds: 5));

      // Tutup dialog pemrosesan setelah operasi selesai
      Navigator.of(context).pop();

      // Simpan riwayat pemberian pakan manual
      await _saveFeedingHistory({
        'time': formattedTime,
        'putaran': 1, // atau nilai yang sesuai
        'type': 'manual'
      });

      // Tampilkan notifikasi "Pemberian pakan selesai" setelah operasi selesai
      Toast.show("Memberi pakan selesai :)");
    } catch (e) {
      // Tutup dialog pemrosesan jika ada kesalahan
      Navigator.of(context).pop();

      // Tampilkan notifikasi kesalahan
      Toast.show("Terjadi kesalahan: $e");
    }
  }

  void showLoadingDialog(BuildContext context) {
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return const AlertDialog(
          content: Row(
            children: [
              CircularProgressIndicator(),
              SizedBox(width: 20),
              Text("Memproses..."),
            ],
          ),
        );
      },
    );
  }
}
