import 'package:diameter/components/detail.dart';
import 'package:diameter/components/forms/boolean_form_field.dart';
import 'package:diameter/utils/dialog_utils.dart';
import 'package:diameter/models/basal.dart';
import 'package:diameter/models/settings.dart';
import 'package:diameter/navigation.dart';
import 'package:diameter/screens/basal/basal_detail.dart';
import 'package:flutter/material.dart';
import 'package:diameter/components/forms/form_wrapper.dart';
import 'package:diameter/models/basal_profile.dart';
import 'package:diameter/screens/basal/basal_list.dart';

class BasalProfileDetailScreen extends StatefulWidget {
  static const String routeName = '/basal-profile';

  final int id;
  final bool active;

  const BasalProfileDetailScreen({Key? key, this.active = false, this.id = 0})
      : super(key: key);

  @override
  _BasalProfileDetailScreenState createState() =>
      _BasalProfileDetailScreenState();
}

class _BasalProfileDetailScreenState extends State<BasalProfileDetailScreen> {
  BasalProfile? _basalProfile;
  List<Basal> _basalRates = [];
  bool _isNew = true;

  final GlobalKey<FormState> _basalProfileForm = GlobalKey<FormState>();
  final ScrollController _scrollController = ScrollController();

  late FloatingActionButton addBasalButton;
  late IconButton refreshButton;
  late IconButton closeButton;
  late DetailBottomRow detailBottomRow;
  late DetailBottomRow detailBottomRowWhileSaving;

  FloatingActionButton? actionButton;
  List<Widget> appBarActions = [];
  DetailBottomRow? bottomNav;

  final _nameController = TextEditingController(text: '');
  final _notesController = TextEditingController(text: '');
  bool _active = false;

  @override
  void initState() {
    super.initState();

    reload();

    if (_basalProfile != null) {
      _nameController.text = _basalProfile!.name;
      _active = _basalProfile!.active;
      _notesController.text = _basalProfile!.notes ?? '';
    }

    if (widget.active) {
      _active = true;
    }

    addBasalButton = FloatingActionButton(
      onPressed: handleAddNewBasal,
      child: const Icon(Icons.add),
    );

    refreshButton = IconButton(
      icon: const Icon(Icons.refresh),
      onPressed: reload,
    );

    closeButton = IconButton(
      onPressed: handleCancelAction,
      icon: const Icon(Icons.close),
    );

    detailBottomRow = DetailBottomRow(
      onCancel: handleCancelAction,
      onAction: handleSaveAction,
      onMiddleAction: () => handleSaveAction(close: true),
    );

    detailBottomRowWhileSaving = DetailBottomRow(
      onCancel: handleCancelAction,
      onAction: null,
    );

    actionButton = null;
    appBarActions = [closeButton];
    bottomNav = detailBottomRow;
  }

  @override
  void dispose() {
    _scrollController.dispose();
    _nameController.dispose();
    _notesController.dispose();
    super.dispose();
  }

  void reload({String? message}) {
    if (widget.id != 0) {
      setState(() {
        _basalProfile = BasalProfile.get(widget.id);
        _basalRates = Basal.getAllForProfile(widget.id);
      });
      _isNew = _basalProfile == null;
    }

    setState(() {
      if (message != null) {
        var snackBar = SnackBar(
          content: Text(message),
          duration: const Duration(seconds: 2),
        );
        ScaffoldMessenger.of(context)
          ..removeCurrentSnackBar()
          ..showSnackBar(snackBar);
      }
    });
  }

  Future<void> checkActiveProfiles() async {
    int _activeCount = BasalProfile.activeCount();

    if (_active &&
        (_activeCount > 1 ||
            _activeCount == 1 && (_isNew || !_basalProfile!.active))) {
      await showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              content: const Text(
                  'There are already one or more active profiles. What would you like to do?'),
              actions: [
                TextButton(
                  onPressed: () => Navigator.pop(context, 0),
                  child: const Text('IGNORE'),
                ),
                TextButton(
                  onPressed: () => Navigator.pop(context, 1),
                  child:
                      Text('DEACTIVATE ${_nameController.text.toUpperCase()}'),
                ),
                ElevatedButton(
                  onPressed: () => Navigator.pop(context, 2),
                  child: const Text('DEACTIVATE ALL OTHERS'),
                )
              ],
            );
          }).then((value) async {
        if (value == 1) {
          setState(() {
            _active = false;
          });
        } else if (value == 2) {
          BasalProfile.setAllInactive();
        }
      });
    } else if (!_active &&
        ((_isNew && _activeCount == 0) ||
            (!_isNew && _activeCount == 1 && _basalProfile!.active))) {
      await showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              content: const Text(
                  'There is currently no active profile. Would you like to set this one as active?'),
              actions: [
                TextButton(
                  onPressed: () => Navigator.pop(context, 0),
                  child: const Text('IGNORE'),
                ),
                TextButton(
                  onPressed: () => Navigator.pop(context, 1),
                  child: const Text('ACTIVATE THIS PROFILE'),
                ),
              ],
            );
          }).then((value) {
        if (value == 1) {
          setState(() {
            _active = true;
          });
        }
      });
    }
  }

  void handleAddNewBasal() async {
    TimeOfDay? suggestedStartTime;
    TimeOfDay? suggestedEndTime;

    if (_basalRates.isEmpty) {
      suggestedStartTime = const TimeOfDay(hour: 0, minute: 0);
      suggestedEndTime = const TimeOfDay(hour: 0, minute: 0);
    } else {
      _basalRates.asMap().forEach((index, basal) {
        if (suggestedStartTime == null && suggestedEndTime == null) {
          if (index == 0 &&
              (basal.startTime.hour != 0 || basal.startTime.minute != 0)) {
            suggestedStartTime = const TimeOfDay(hour: 0, minute: 0);
            suggestedEndTime = TimeOfDay.fromDateTime(basal.startTime);
          } else if ((index == _basalRates.length - 1) &&
              (basal.endTime.hour != 0 || basal.endTime.minute != 0)) {
            suggestedStartTime = TimeOfDay.fromDateTime(basal.endTime);
            suggestedEndTime = const TimeOfDay(hour: 0, minute: 0);
          } else if (index != 0) {
            var lastEndTime = _basalRates[index - 1].endTime;
            if (basal.startTime.isAfter(lastEndTime)) {
              suggestedStartTime = TimeOfDay.fromDateTime(lastEndTime);
              suggestedEndTime = TimeOfDay.fromDateTime(basal.startTime);
            }
          }
        }
      });
    }

    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) {
          return BasalDetailScreen(
            basalProfileId: widget.id,
            suggestedStartTime: suggestedStartTime,
            suggestedEndTime: suggestedEndTime,
          );
        },
      ),
    ).then((result) => reload(message: result?[0]));
  }

  void handleSaveAction({bool close = false}) async {
    setState(() {
      bottomNav = detailBottomRowWhileSaving;
    });
    if (_basalProfileForm.currentState!.validate()) {
      await checkActiveProfiles();
      BasalProfile basalProfile = BasalProfile(
        id: widget.id,
        name: _nameController.text,
        active: _active,
        notes: _notesController.text,
      );
      BasalProfile.put(basalProfile);

      if (close) {
        Navigator.pop(context,
            ['${_isNew ? 'New' : ''} Basal Profile saved', basalProfile]);
      } else {
        if (_isNew) {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) =>
                  BasalProfileDetailScreen(id: basalProfile.id),
            ),
          ).then((result) => Navigator.pop(context, result));
        } else {
          reload(message: 'Basal Profile saved');
        }
      }
    }
    setState(() {
      bottomNav = detailBottomRow;
    });
  }

  void handleCancelAction() {
    if (Settings.get().showConfirmationDialogOnCancel &&
            (_isNew &&
                (_active != widget.active ||
                    _nameController.text != '' ||
                    _notesController.text != '')) ||
        (!_isNew &&
            (_basalProfile!.active != _active ||
                _basalProfile!.name != _nameController.text ||
                (_basalProfile!.notes ?? '') != _notesController.text))) {
      DialogUtils.showCancelConfirmationDialog(
        context: context,
        isNew: _isNew,
        onSave: handleSaveAction,
      );
    } else {
      Navigator.pop(context);
    }
  }

  void renderTabButtons(index) {
    if (_basalProfile != null) {
      setState(() {
        switch (index) {
          case 1:
            actionButton = addBasalButton;
            appBarActions = [refreshButton, closeButton];
            bottomNav = null;
            break;
          default:
            actionButton = null;
            appBarActions = [closeButton];
            bottomNav = detailBottomRow;
        }
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: _isNew ? 1 : 2,
      child: Builder(builder: (BuildContext context) {
        final TabController tabController = DefaultTabController.of(context)!;
        tabController.addListener(() {
          renderTabButtons(tabController.index);
        });
        List<Widget> tabs = [
          Scrollbar(
            controller: _scrollController,
            child: SingleChildScrollView(
              controller: _scrollController,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  FormWrapper(
                    formState: _basalProfileForm,
                    fields: [
                      TextFormField(
                        controller: _nameController,
                        decoration: const InputDecoration(
                          labelText: 'Name',
                        ),
                        validator: (value) {
                          if (value!.trim().isEmpty) {
                            return 'Empty title';
                          }
                          return null;
                        },
                      ),
                      TextFormField(
                        keyboardType: TextInputType.multiline,
                        controller: _notesController,
                        decoration: const InputDecoration(
                          labelText: 'Notes',
                        ),
                        minLines: 2,
                        maxLines: 5,
                      ),
                      BooleanFormField(
                        value: _active,
                        onChanged: (value) {
                          setState(() {
                            _active = value;
                          });
                        },
                        label: 'active',
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ];

        if (!_isNew) {
          tabs.add(BasalListScreen(
              basalProfile: _basalProfile!,
              basalRates: _basalRates,
              reload: reload));
        }

        return Scaffold(
          appBar: AppBar(
            title: Text(_isNew ? 'New Basal Profile' : _basalProfile!.name),
            bottom: _isNew
                ? PreferredSize(child: Container(), preferredSize: Size.zero)
                : const TabBar(
                    tabs: [
                      Tab(text: 'PROFILE'),
                      Tab(text: 'RATES'),
                    ],
                  ),
            actions: appBarActions,
          ),
          drawer: const Navigation(
              currentLocation: BasalProfileDetailScreen.routeName),
          body: TabBarView(children: tabs),
          bottomNavigationBar: bottomNav,
          floatingActionButton: actionButton,
          floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
        );
      }),
    );
  }
}
