import 'dart:convert';

import 'package:drift/drift.dart' hide Column;
import 'package:flutter/material.dart' hide Action;
import 'package:provider/provider.dart';
import 'package:sendtrain/daos/actions_dao.dart';
import 'package:sendtrain/daos/activity_actions_dao.dart';
import 'package:sendtrain/database/database.dart';
import 'package:sendtrain/helpers/widget_helpers.dart';
import 'package:sendtrain/widgets/generic/elements/form_drop_down.dart';
import 'package:sendtrain/widgets/generic/elements/form_text_input.dart';

class ActivityActionEditor extends StatefulWidget {
  const ActivityActionEditor(
      {super.key,
      required this.session,
      required this.activity,
      this.action,
      this.callback});

  final Session session;
  final Activity activity;
  final Action? action;
  final Function? callback;

  @override
  State<ActivityActionEditor> createState() => _ActivityActionEditorState();
}

class _ActivityActionEditorState extends State<ActivityActionEditor> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  final Map<String, TextEditingController> actionEditController = {
    'sets': TextEditingController(),
    'reps': TextEditingController(),
    'weight': TextEditingController(),
    'repLength': TextEditingController(),
    'preparation': TextEditingController(),
    'setRest': TextEditingController(),
    'repRest': TextEditingController(),
    'cooldown': TextEditingController(),
    'type': TextEditingController(),
    'alternating': TextEditingController(),
  };

  late final AppDatabase db;

  bool isAlternating = false;
  bool isTimed = false;
  String editorType = 'Create';

  @override
  void initState() {
    super.initState();
    db = Provider.of<AppDatabase>(context, listen: false);

    // if we're editing a session, we'll want to populate it with the appropriate values
    if (widget.action != null) {
      final Action action = widget.action!;
      editorType = 'Edit';
      isAlternating = action.isAlternating;
      isTimed = action.repType == RepType.time ? true : false;

      actionEditController['sets']?.text = action.totalSets.toString();
      actionEditController['reps']?.text =
          json.decode(action.totalReps)[0].toString();
      actionEditController['weight']?.text =
          json.decode(action.repWeights ?? "")[0].toString();
      actionEditController['repLength']?.text =
          ((action.repLength ?? 0) ~/ 1000).toString();
      actionEditController['preparation']?.text =
          ((action.restBeforeSets ?? 0) ~/ 1000).toString();
      actionEditController['setRest']?.text =
          ((action.restBetweenSets ?? 0) ~/ 1000).toString();
      actionEditController['repRest']?.text =
          ((action.restBetweenReps ?? 0) ~/ 1000).toString();
      actionEditController['cooldown']?.text =
          ((action.restAfterSets ?? 0) ~/ 1000).toString();
      actionEditController['isTimed']?.text = isTimed.toString();
      actionEditController['alternating']?.text = isAlternating.toString();
    }
  }

  @override
  Widget build(BuildContext context) {
    if (widget.action != null) {
      editorType = 'Edit';
    }

    return Padding(
        padding: EdgeInsets.fromLTRB(15, 0, 15, 15),
        child: Form(
            key: _formKey,
            child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Padding(
                      padding: EdgeInsets.only(top: 10, bottom: 10),
                      child: Text('$editorType Action',
                          textAlign: TextAlign.center,
                          style: Theme.of(context).textTheme.titleLarge)),
                  Row(children: [
                    formItemWrapper(
                        CheckboxListTile(
                          title: Text("Reps alternate? (eg. Left/Right Hand)"),
                          value: isAlternating,
                          shape: RoundedRectangleBorder(
                            borderRadius:
                                BorderRadius.all(Radius.circular(10.0)),
                          ),
                          onChanged: (bool? value) {
                            setState(() {
                              isAlternating = value!;
                            });
                          },
                        ),
                        EdgeInsets.fromLTRB(10, 10, 10, 10)),
                  ]),
                  Row(children: [
                    formItemWrapper(
                        CheckboxListTile(
                          title: Text("Are reps timed?"),
                          value: isTimed,
                          shape: RoundedRectangleBorder(
                            borderRadius:
                                BorderRadius.all(Radius.circular(10.0)),
                          ),
                          onChanged: (bool? value) {
                            setState(() {
                              isTimed = value!;
                            });
                          },
                        ),
                        EdgeInsets.fromLTRB(10, 10, 10, 15))
                  ]),
                  Row(children: [
                    FormDropDown(
                        title: 'Sets',
                        entries: numericDropDownItems('Set', 50),
                        controller: actionEditController['sets']!),
                    FormDropDown(
                      title: 'Reps',
                      entries: numericDropDownItems('Rep', 100),
                      controller: actionEditController['reps']!,
                    )
                  ]),
                  Row(children: [
                    formItemWrapper(
                        FormTextInput(
                            type: InputTypes.number,
                            controller: actionEditController['preparation']!,
                            title: 'Preparation (sec)',
                            hint: 'time before start',
                            requiresValidation: false),
                        EdgeInsets.fromLTRB(10, 5, 10, 0)),
                    formItemWrapper(
                        FormTextInput(
                            type: InputTypes.number,
                            controller: actionEditController['cooldown']!,
                            title: 'Cooldown (sec)',
                            hint: 'rest after completion',
                            requiresValidation: false),
                        EdgeInsets.fromLTRB(10, 5, 10, 0)),
                  ]),
                  Row(children: [
                    formItemWrapper(
                        FormTextInput(
                            type: InputTypes.number,
                            controller: actionEditController['setRest']!,
                            title: 'Set Rest (sec)',
                            hint: 'Rest between sets',
                            requiresValidation: false),
                        EdgeInsets.only(left: 10, right: 10)),
                    formItemWrapper(
                        FormTextInput(
                            type: InputTypes.number,
                            controller: actionEditController['repRest']!,
                            title: 'Rep Rest (sec)',
                            hint: 'Rest between reps',
                            requiresValidation: false),
                        EdgeInsets.only(left: 10, right: 10)),
                  ]),
                  Row(children: [
                    formItemWrapper(
                        FormTextInput(
                            type: InputTypes.number,
                            controller: actionEditController['repLength']!,
                            title: 'Rep Length (sec)',
                            hint: 'Total rep time (not required)',
                            requiresValidation: false),
                        EdgeInsets.only(left: 10, right: 10)),
                    formItemWrapper(
                        FormTextInput(
                            type: InputTypes.number,
                            controller: actionEditController['weight']!,
                            title: 'Weight',
                            hint: 'Weight for reps',
                            requiresValidation: false),
                        EdgeInsets.only(left: 10, right: 10)),
                  ]),
                  Row(mainAxisAlignment: MainAxisAlignment.end, children: [
                    Padding(
                        padding: EdgeInsets.only(top: 10, right: 10),
                        child: FilledButton(
                            onPressed: () async {
                              if (_formKey.currentState!.validate()) {
                                if (widget.action != null) {
                                  Action newAction = widget.action!.copyWith(
                                    totalSets: int.parse(
                                        actionEditController['sets']!.text),
                                    totalReps: json.encode([
                                      int.parse(
                                          actionEditController['reps']!.text)
                                    ]),
                                    repLength: Value<int>(int.parse(
                                            actionEditController['repLength']!
                                                .text) *
                                        1000),
                                    restBeforeSets: Value<int>(int.parse(
                                            actionEditController['preparation']!
                                                .text) *
                                        1000),
                                    restBetweenSets: Value<int>(int.parse(
                                            actionEditController['setRest']!
                                                .text) *
                                        1000),
                                    restBetweenReps: Value<int>(int.parse(
                                            actionEditController['repRest']!
                                                .text) *
                                        1000),
                                    restAfterSets: Value<int>(int.parse(
                                            actionEditController['cooldown']!
                                                .text) *
                                        1000),
                                    repType: int.parse(actionEditController[
                                                    'repLength']!
                                                .text) >
                                            0
                                        ? RepType.time
                                        : RepType.count,
                                    repWeights: Value<String>(json.encode([
                                      int.parse(
                                          actionEditController['weight']!.text)
                                    ])),
                                    // setWeights: Value<String>(json.encode([actionEditController['setWeights']!.text])),
                                    isAlternating: isAlternating,
                                  );

                                  // var result = await ActionsDao(db).createOrUpdate(
                                  //     newAction.toCompanion(true));
                                  await ActionsDao(db).replace(newAction);
                                } else {
                                  // create action
                                  await ActionsDao(db)
                                      .createOrUpdate(ActionsCompanion(
                                          title: Value('title'),
                                          description: Value('description'),
                                          totalSets: Value(int.parse(
                                              actionEditController['sets']!
                                                  .text)),
                                          totalReps: Value(json.encode(
                                              [int.parse(actionEditController['reps']!.text)])),
                                          repLength: Value<int>(
                                              int.parse(actionEditController['repLength']!.text) *
                                                  1000),
                                          restBeforeSets: Value<int>(
                                              int.parse(actionEditController['preparation']!.text) *
                                                  1000),
                                          restBetweenSets: Value<int>(
                                              int.parse(actionEditController['setRest']!.text) *
                                                  1000),
                                          restBetweenReps:
                                              Value<int>(int.parse(actionEditController['repRest']!.text) * 1000),
                                          restAfterSets: Value<int>(int.parse(actionEditController['cooldown']!.text) * 1000),
                                          repType: Value(int.parse(actionEditController['repLength']!.text) > 0 ? RepType.time : RepType.count),
                                          repWeights: Value<String>(json.encode([int.parse(actionEditController['weight']!.text)])),
                                          // setWeights: Value<String>(json.encode([actionEditController['setWeights']!.text])),
                                          isAlternating: Value<bool>(isAlternating),
                                          // repType: RepType.values.firstWhere((e) => e.toString() == "RepType.${actionEditController['repType']!.text}"),
                                          set: Value("")))
                                      .then((actionId) {
                                    ActivityActionsDao(db).createOrUpdate(
                                        ActivityActionsCompanion(
                                            activityId:
                                                Value(widget.activity.id),
                                            sessionId: Value(widget.session.id),
                                            actionId: Value(actionId),
                                            position: Value(0)));
                                  });
                                }

                                Navigator.pop(
                                    _formKey.currentContext!, 'Submit');

                                if (widget.callback != null) {
                                  await widget.callback!();
                                }
                              }
                            },
                            child: Text('Submit')))
                  ])
                ])));
  }
}
