import 'dart:async';
import 'dart:convert';
import 'dart:developer';

import 'package:flutter/material.dart';
import '../../product/shared/shared_component_loading_animation.dart';
import '../../product/shared/shared_loading_animation.dart';
import '../../product/shared/shared_snack_bar.dart';
import 'shared/alert_card.dart';
import 'shared/warning_card.dart';
import '../../product/utils/device_utils.dart';
import 'device_alias_model.dart';
import 'shared/overview_card.dart';
import '../settings/device_notification_settings/device_notification_settings_model.dart';
import '../../product/extension/context_extension.dart';
import '../../product/services/api_services.dart';
import '../../product/services/language_services.dart';
import '../../bloc/home_bloc.dart';
import '../../product/base/bloc/base_bloc.dart';

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  late HomeBloc homeBloc;
  APIServices apiServices = APIServices();
  Map<String, List<DeviceWithAlias>> allDevicesAliasMap = {};
  Map<String, List<DeviceWithAlias>> allDevicesAliasJoinedMap = {};
  List<DeviceWithAlias> devices = [];
  bool isFunctionCall = false;
  Timer? getAllDevicesTimer;
  int notificationCount = 0;
  Map<String, List<DeviceWithAlias>> ownerDevicesStatus = {};
  List<String> ownerDevicesState = [];

  @override
  void initState() {
    super.initState();
    homeBloc = BlocProvider.of(context);
    getOwnerAndJoinedDevices();
    const duration = Duration(seconds: 10);
    getAllDevicesTimer =
        Timer.periodic(duration, (Timer t) => getOwnerAndJoinedDevices());
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: context.paddingLow,
        child: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              Row(
                children: [
                  Text(
                    appLocalization(context).notification,
                    style: context.titleMediumTextStyle,
                  ),
                  SizedBox(width: context.lowValue),
                  StreamBuilder<int>(
                    stream: homeBloc.streamCountNotification,
                    builder: (context, countSnapshot) {
                      return Text(
                        "(${countSnapshot.data ?? 0})",
                        style: context.titleMediumTextStyle,
                      );
                    },
                  )
                ],
              ),
              SizedBox(
                child: SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: StreamBuilder<Map<String, List<DeviceWithAlias>>>(
                    stream: homeBloc.streamOwnerDevicesStatus,
                    builder: (context, snapshot) {
                      return AnimatedSwitcher(
                        duration: context.lowDuration,
                        transitionBuilder:
                            (Widget child, Animation<double> animation) {
                          final offsetAnimation = Tween<Offset>(
                            begin: const Offset(0.0, 0.2),
                            end: Offset.zero,
                          ).animate(CurvedAnimation(
                            parent: animation,
                            curve: Curves.easeInOut,
                          ));
                          return FadeTransition(
                            opacity: animation,
                            child: SlideTransition(
                              position: offsetAnimation,
                              child: child,
                            ),
                          );
                        },
                        child: snapshot.data?['state'] != null ||
                                snapshot.data?['battery'] != null
                            ? ConstrainedBox(
                                key: const ValueKey('data'),
                                constraints: BoxConstraints(
                                    minWidth:
                                        MediaQuery.of(context).size.width),
                                child: Row(
                                  mainAxisAlignment: MainAxisAlignment.start,
                                  children: [
                                    if (snapshot.data?['state'] != null)
                                      ...snapshot.data!['state']!
                                          .map(
                                            (item) => SizedBox(
                                              width: context.dynamicWidth(0.95),
                                              child: FutureBuilder<Widget>(
                                                future: warningCard(
                                                    context, apiServices, item),
                                                builder: (context,
                                                    warningCardSnapshot) {
                                                  if (warningCardSnapshot
                                                      .hasData) {
                                                    return warningCardSnapshot
                                                        .data!;
                                                  } else {
                                                    return const SizedBox
                                                        .shrink();
                                                  }
                                                },
                                              ),
                                            ),
                                          )
                                          .toList(),
                                    if (snapshot.data?['battery'] != null)
                                      ...snapshot.data!['battery']!
                                          .map(
                                            (batteryItem) => SizedBox(
                                              width: context.dynamicWidth(0.95),
                                              child: FutureBuilder<Widget>(
                                                future: notificationCard(
                                                  context,
                                                  "lowBattery",
                                                  appLocalization(context)
                                                      .low_battery_message,
                                                  batteryItem,
                                                ),
                                                builder: (context,
                                                    warningCardSnapshot) {
                                                  if (warningCardSnapshot
                                                      .hasData) {
                                                    return warningCardSnapshot
                                                        .data!;
                                                  } else {
                                                    return const SizedBox
                                                        .shrink();
                                                  }
                                                },
                                              ),
                                            ),
                                          )
                                          .toList(),
                                  ],
                                ),
                              )
                            : Padding(
                                key: const ValueKey('no_data'),
                                padding: context.paddingMedium,
                                child: Center(
                                  child: Row(
                                    mainAxisSize: MainAxisSize.min,
                                    children: [
                                      const Icon(
                                        Icons.check_circle_outline_rounded,
                                        size: 40,
                                        color: Colors.green,
                                      ),
                                      SizedBox(width: context.lowValue),
                                      Text(
                                        appLocalization(context)
                                            .notification_description,
                                        maxLines: 2,
                                        overflow: TextOverflow.ellipsis,
                                        softWrap: true,
                                        textAlign: TextAlign.start,
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                      );
                    },
                  ),
                ),
              ),
              StreamBuilder<bool?>(
                stream: homeBloc.streamHasJoinedDevice,
                initialData: null,
                builder: (context, hasJoinedDeviceSnapshot) {
                  return StreamBuilder<Map<String, List<DeviceWithAlias>>>(
                    stream: homeBloc.streamAllDevicesAliasMap,
                    builder: (context, allDevicesAliasMapSnapshot) {
                      return StreamBuilder<Map<String, List<DeviceWithAlias>>>(
                        stream: homeBloc.streamAllDevicesAliasJoinedMap,
                        builder: (context, allDevicesAliasJoinedMapSnapshot) {
                          if (hasJoinedDeviceSnapshot.data == null) {
                            return const SharedComponentLoadingAnimation();
                          } else {
                            final data = allDevicesAliasMapSnapshot.data!;
                            final dataJoined =
                                allDevicesAliasJoinedMapSnapshot.data!;
                            if (hasJoinedDeviceSnapshot.data == false) {
                              if (!allDevicesAliasMapSnapshot.hasData ||
                                  allDevicesAliasMapSnapshot.data == null) {
                                return const Center(
                                    child: CircularProgressIndicator());
                              }

                              return OverviewCard(
                                isOwner: true,
                                total: data['all']?.length ?? 0,
                                active: data['online']?.length ?? 0,
                                inactive: data['offline']?.length ?? 0,
                                warning: data['warn']?.length ?? 0,
                                unused: data['not-use']?.length ?? 0,
                                showUnused: false,
                              );
                            } else {
                              return DefaultTabController(
                                length: 2,
                                child: Column(
                                  // mainAxisSize: MainAxisSize.min,
                                  // crossAxisAlignment: CrossAxisAlignment.start,
                                  children: [
                                    TabBar(
                                      tabs: [
                                        Tab(
                                            text: appLocalization(context)
                                                .over_view_owner_devices),
                                        Tab(
                                            text: appLocalization(context)
                                                .over_view_joined_devices),
                                      ],
                                      labelColor: Colors.blue,
                                      unselectedLabelColor: Colors.grey,
                                      indicatorColor: Colors.blue,
                                    ),
                                    ConstrainedBox(
                                      constraints: BoxConstraints(
                                        maxHeight: context.dynamicHeight(0.5),
                                        minHeight: context.dynamicHeight(0.3),
                                      ),
                                      child: TabBarView(
                                        children: [
                                          OverviewCard(
                                            isOwner: true,
                                            total: data['all']?.length ?? 0,
                                            active: data['online']?.length ?? 0,
                                            inactive:
                                                data['offline']?.length ?? 0,
                                            warning: data['warn']?.length ?? 0,
                                            unused:
                                                data['not-use']?.length ?? 0,
                                            showUnused: false,
                                          ),
                                          OverviewCard(
                                            isOwner: false,
                                            total:
                                                dataJoined['all']?.length ?? 0,
                                            active:
                                                dataJoined['online']?.length ??
                                                    0,
                                            inactive:
                                                dataJoined['offline']?.length ??
                                                    0,
                                            warning:
                                                dataJoined['warn']?.length ?? 0,
                                            unused:
                                                dataJoined['not-use']?.length ??
                                                    0,
                                            showUnused: false,
                                            showActive: false,
                                            showInactive: false,
                                          ),
                                        ],
                                      ),
                                    ),
                                  ],
                                ),
                              );
                            }
                          }
                        },
                      );
                    },
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

  void getOwnerAndJoinedDevices() async {
    try {
      devices = await apiServices.getDashBoardDevices();
      List<DeviceWithAlias> publicDevices = [];
      for (var device in devices) {
        if (device.visibility == "PUBLIC") {
          publicDevices.add(device);
        }
      }
      getOwnerDeviceState(publicDevices);
      checkSettingDevice(publicDevices);
      getDeviceStatusAliasMap(publicDevices);
    } catch (e) {
      if (!mounted) return;
      showErrorTopSnackBarCustom(context, e.toString());
    }
  }

  void getOwnerDeviceState(List<DeviceWithAlias> allDevices) async {
    ownerDevicesState.clear();
    ownerDevicesStatus.clear();

    if (!mounted) return;
    homeBloc.sinkOwnerDevicesStatus.add(ownerDevicesStatus);

    int count = 0;
    for (var device in allDevices) {
      if (device.isOwner != true) continue;

      if (!mounted) return;
      Map<String, dynamic> sensorMap = DeviceUtils.instance
          .getDeviceSensors(context, device.status?.sensors ?? []);

      if (device.state == 1 || device.state == 3) {
        ownerDevicesStatus["state"] ??= [];
        ownerDevicesStatus["state"]!.add(device);
        if (!mounted) return;
        homeBloc.sinkOwnerDevicesStatus.add(ownerDevicesStatus);
        count++;
      }

      final noDataMessage = appLocalization(context).no_data_message;
      if (sensorMap['sensorBattery'] != noDataMessage) {
        if (double.parse(sensorMap['sensorBattery']) <= 20) {
          ownerDevicesStatus['battery'] ??= [];
          ownerDevicesStatus['battery']!.add(device);
          if (!mounted) return;
          homeBloc.sinkOwnerDevicesStatus.add(ownerDevicesStatus);
          count++;
        }
      }
    }

    notificationCount = count;
    if (!mounted) return;
    homeBloc.sinkCountNotification.add(notificationCount);
  }

  void getDeviceStatusAliasMap(List<DeviceWithAlias> devices) {
    allDevicesAliasMap.clear();
    allDevicesAliasJoinedMap.clear();
    bool check = false;
    for (var key in ['all', 'online', 'offline', 'warning', 'not-use']) {
      allDevicesAliasMap[key] = [];
      allDevicesAliasJoinedMap[key] = [];
    }

    for (DeviceWithAlias device in devices) {
      if (device.isOwner == true) {
        allDevicesAliasMap['all']!.add(device);
        if (device.state == 0 || device.state == 1) {
          allDevicesAliasMap['online']!.add(device);
        }
        if (device.state == -1) {
          allDevicesAliasMap['offline']!.add(device);
        }
        if (device.state == 1) {
          allDevicesAliasMap['warning']!.add(device);
        }
        if (device.state == -2) {
          allDevicesAliasMap['not-use']!.add(device);
        }
      } else {
        check = true;
        allDevicesAliasJoinedMap['all']!.add(device);
        if (device.state == 0 || device.state == 1) {
          allDevicesAliasJoinedMap['online']!.add(device);
        }
        if (device.state == -1) {
          allDevicesAliasJoinedMap['offline']!.add(device);
        }
        if (device.state == 1) {
          allDevicesAliasJoinedMap['warning']!.add(device);
        }
        if (device.state == -2) {
          allDevicesAliasJoinedMap['not-use']!.add(device);
        }
      }
    }
    homeBloc.sinkHasJoinedDevice.add(check);
    homeBloc.sinkAllDevicesAliasMap.add(allDevicesAliasMap);
    homeBloc.sinkAllDevicesAliasJoinedMap.add(allDevicesAliasJoinedMap);
  }

  void checkSettingDevice(List<DeviceWithAlias> devices) async {
    try {
      if (isFunctionCall) {
        log("Ham check setting da duoc goi");
      } else {
        List<DeviceNotificationSettings> list =
            await apiServices.getAllSettingsNotificationOfDevices();
        // log("List: $list");
        Set<String> thingIdsInList =
            list.map((device) => device.thingId!).toSet();
        for (var device in devices) {
          if (!thingIdsInList.contains(device.thingId)) {
            log("Device with Thing ID ${device.thingId} is not in the notification settings list.");
            try {
              await apiServices.setupDeviceNotification(
                  device.thingId!, device.name!);
            } catch (e) {
              if (!mounted) return;
              showErrorTopSnackBarCustom(
                  context, e.toString());
            }

          } else {
            log("All devices are in the notification settings list.");
          }
        }
      }
      isFunctionCall = true;
    } catch (e) {
      if (!mounted) return;
      showErrorTopSnackBarCustom(context, e.toString());
    }
  }
}
