import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:multi_dropdown/multiselect_dropdown.dart';
import 'package:searchable_paginated_dropdown/searchable_paginated_dropdown.dart';
import 'package:searchfield/searchfield.dart';
import 'package:unit2/bloc/rbac/rbac_bloc.dart';
import 'package:unit2/bloc/user/user_bloc.dart';
import 'package:unit2/model/rbac/new_permission.dart';
import 'package:unit2/model/rbac/permission.dart';
import 'package:unit2/model/rbac/rbac.dart';
import 'package:unit2/theme-data.dart/btn-style.dart';
import 'package:unit2/theme-data.dart/colors.dart';
import 'package:unit2/widgets/error_state.dart';
import '../../../../model/profile/basic_information/primary-information.dart';
import '../../../../sevices/roles/rbac_services.dart';
import '../../../../theme-data.dart/box_shadow.dart';
import '../../../../theme-data.dart/form-style.dart';
import '../../../../utils/alerts.dart';
import 'add_rbac.dart';

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

  @override
  State<RBACScreen> createState() => _RBACScreenState();
}

class _RBACScreenState extends State<RBACScreen> {
  ////roles
  final roleFocusNode = FocusNode();
  final roleController = TextEditingController();
  RBAC? selectedRole;

  ////modules
  final moduleFocusNode = FocusNode();
  final moduleController = TextEditingController();
  RBAC? selectedModule;

////permissions
  final permissionFocusNode = FocusNode();
  final permissionController = TextEditingController();
  List<ValueItem> valueItemSelectedPermissions = [];
  List<ValueItem> valueItemPermission = [];

////Object
  RBAC? selectedObject;
  final objectFocusNode = FocusNode();
  final objectController = TextEditingController();

  ////operations
  List<int> operationsId = [];
  List<RBAC> newOperations = [];
  List<ValueItem> valueItemOperation = [];
  List<ValueItem> selectedValueItemOperation = [];

  String? token;

  ////new permission
  List<NewPermission> newPermissions = [];

  final formKey = GlobalKey<FormBuilderState>();
  final addRbacFormKey = GlobalKey<FormBuilderState>();
  final newOperationKey = GlobalKey<FormBuilderState>();
  int? selectedWebUserId;
  bool showAddOperations = false;
  @override
  void dispose() {
    moduleFocusNode.dispose();
    moduleController.dispose();
    roleFocusNode.dispose();
    roleController.dispose();
    permissionFocusNode.dispose();
    permissionController.dispose();
    objectFocusNode.dispose();
    objectController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        resizeToAvoidBottomInset: false,
        appBar: AppBar(
          title: const FittedBox(
            child: Text("Role Based Access Control"),
          ),
          backgroundColor: primary,
        ),
        body: ProgressHUD(
          padding: const EdgeInsets.all(24),
          backgroundColor: Colors.black87,
          indicatorWidget: const SpinKitFadingCircle(color: Colors.white),
          child: BlocBuilder<UserBloc, UserState>(
            builder: (context, state) {
              if (state is UserLoggedIn) {
                token = state.userData!.user!.login!.token;
                return BlocConsumer<RbacBloc, RbacState>(
                  listener: (context, state) {
                    final progress = ProgressHUD.of(context);
                    progress!.showWithText("Please wait...");
                    if (state is RbacScreenSetted || state is RbacErrorState) {
                      final progress = ProgressHUD.of(context);
                      progress!.dismiss();
                    }
                    if (state is RbacAssignedState) {
                      if (state.responseStatus['success']) {
                        successAlert(context, "Assigning Successfull!",
                            state.responseStatus['message'], () {
                          Navigator.of(context).pop();
                          context.read<RbacBloc>().add(LoadRbac());
                        });
                      } else {
                        errorAlert(context, "Assigning Failed!",
                            state.responseStatus['message'], () {
                          Navigator.of(context).pop();
                          context.read<RbacBloc>().add(LoadRbac());
                        });
                      }
                    }
                  },
                  builder: (context, state) {
                    if (state is RbacScreenSetted) {
                      //// permission value item
                      valueItemPermission =
                          state.permission.map((RBACPermission permission) {
                        return ValueItem(
                            label:
                                "${permission.operation?.name} - ${permission.object?.name!}",
                            value: permission.id.toString());
                      }).toList();
                      ////value item operation
                      valueItemOperation =
                          state.operations.map((RBAC operation) {
                        return ValueItem(
                            label: operation.name!,
                            value: operation.id.toString());
                      }).toList();
                      return Container(
                        padding: const EdgeInsets.symmetric(
                            vertical: 32, horizontal: 34),
                        child: FormBuilder(
                            key: formKey,
                            child: Column(
                              children: [
                                const SizedBox(
                                  height: 38,
                                ),
                                Flexible(
                                    child: Column(
                                  children: [
                                    ////users
                                    SearchableDropdownFormField.paginated(
                                      margin: const EdgeInsets.all(0),
                                      trailingIcon: const Padding(
                                          padding: EdgeInsets.only(right: 8),
                                          child: Icon(
                                            Icons.arrow_drop_down,
                                            color: Colors.grey,
                                          )),
                                      hintText: const Padding(
                                          padding: EdgeInsets.only(left: 8),
                                          child: Text(
                                            "Search User",
                                            style: TextStyle(
                                                color: Colors.grey,
                                                fontSize: 16),
                                          )),
                                      searchHintText: "Search User",
                                      backgroundDecoration: (child) {
                                        return SizedBox(
                                            width: double.infinity,
                                            child: Container(
                                              width: double.infinity,
                                              height: 50,
                                              decoration: BoxDecoration(
                                                  border: Border.all(
                                                      color: Colors.grey),
                                                  borderRadius:
                                                      const BorderRadius.all(
                                                          Radius.circular(5))),
                                              child: child,
                                            ));
                                      },
                                      paginatedRequest:
                                          (int page, String? searchKey) async {
                                        List<Profile> users = await RbacServices
                                            .instance
                                            .searchUser(
                                                page: page,
                                                name: searchKey ??= "",
                                                token: token!);
                                        return users.map((e) {
                                          String fullname =
                                              "${e.firstName} ${e.lastName}";
                                          return SearchableDropdownMenuItem<
                                              Profile>(
                                            label: fullname,
                                            child: ListTile(
                                              title: Text(fullname),
                                              subtitle:
                                                  Text(e.birthdate.toString()),
                                            ),
                                            onTap: () {
                                              setState(() {
                                                selectedWebUserId = e.webuserId;
                                              });
                                            },
                                          );
                                        }).toList();
                                      },
                                    ),

                                    const SizedBox(
                                      height: 12,
                                    ),
                                    ////Role
                                    StatefulBuilder(
                                        builder: (context, setState) {
                                      return SearchField(
                                          itemHeight: 40,
                                          suggestionsDecoration: searchFieldDecoration(),
                                          suggestions: state.role
                                              .map((RBAC role) =>
                                                  SearchFieldListItem(
                                                      role.name!,
                                                      item: role,
                                                      child: Padding(
                                                        padding:
                                                            const EdgeInsets
                                                                    .symmetric(
                                                                horizontal: 10),
                                                        child: ListTile(
                                                            title: Text(
                                                          role.name!,
                                                          overflow: TextOverflow
                                                              .visible,
                                                        )),
                                                      )))
                                              .toList(),
                                          validator: (agency) {
                                            if (agency!.isEmpty) {
                                              return "This field is required";
                                            }
                                            return null;
                                          },
                                          focusNode: roleFocusNode,
                                          searchInputDecoration:
                                              normalTextFieldStyle("Role *", "")
                                                  .copyWith(
                                                      suffixIcon: IconButton(
                                            icon: const Icon(
                                                Icons.arrow_drop_down),
                                            onPressed: () {
                                              roleFocusNode.unfocus();
                                            },
                                          )),
                                          onSuggestionTap: (role) {
                                            setState(() {
                                              selectedRole = role.item;
                                              roleFocusNode.unfocus();
                                            });
                                          },
                                          ////Add new role
                                          emptyWidget: AddRbac(
                                            formKey: addRbacFormKey,
                                            title: "Add Role",
                                            onpressed: () {
                                              RBAC? newRole;
                                              if (addRbacFormKey.currentState!
                                                  .saveAndValidate()) {
                                                newRole = RBAC(
                                                    id: null,
                                                    name: addRbacFormKey
                                                        .currentState
                                                        ?.value['object_name'],
                                                    slug: addRbacFormKey
                                                        .currentState
                                                        ?.value['slug'],
                                                    shorthand: addRbacFormKey
                                                        .currentState
                                                        ?.value['shorthand'],
                                                    fontawesomeIcon: null,
                                                    createdAt: null,
                                                    updatedAt: null,
                                                    createdBy: null,
                                                    updatedBy: null);
                                              }
                                              setState(() {
                                                state.role.insert(0, newRole!);
                                              });
                                              roleFocusNode.unfocus();
                                              Navigator.pop(context);
                                            },
                                          ));
                                    }),
                                    const SizedBox(
                                      height: 12,
                                    ),
                                    // //// Modules
                                    StatefulBuilder(
                                        builder: (context, setState) {
                                      return SearchField(
                                          itemHeight: 40,
                                          suggestionsDecoration: searchFieldDecoration(),
                                          suggestions: state.modules
                                              .map((RBAC module) =>
                                                  SearchFieldListItem(
                                                      module.name!,
                                                      item: module,
                                                      child: Padding(
                                                        padding:
                                                            const EdgeInsets
                                                                    .symmetric(
                                                                horizontal: 10),
                                                        child: ListTile(
                                                            title: Text(
                                                          module.name!,
                                                          overflow: TextOverflow
                                                              .visible,
                                                        )),
                                                      )))
                                              .toList(),
                                          validator: (module) {
                                            if (module!.isEmpty) {
                                              return "This field is required";
                                            }
                                            return null;
                                          },
                                          focusNode: moduleFocusNode,
                                          searchInputDecoration:
                                              normalTextFieldStyle(
                                                      "Module *", "")
                                                  .copyWith(
                                                      suffixIcon: IconButton(
                                            icon: const Icon(
                                                Icons.arrow_drop_down),
                                            onPressed: () {
                                              moduleFocusNode.unfocus();
                                            },
                                          )),
                                          onSuggestionTap: (module) {
                                            setState(() {
                                              selectedModule = module.item;
                                              moduleFocusNode.unfocus();
                                            });
                                          },
                                          //       //// Add new module

                                          emptyWidget: AddRbac(
                                            formKey: addRbacFormKey,
                                            title: "Add Module",
                                            onpressed: () {
                                              RBAC? newModule;
                                              if (addRbacFormKey.currentState!
                                                  .saveAndValidate()) {
                                                newModule = RBAC(
                                                    id: null,
                                                    name: addRbacFormKey
                                                        .currentState
                                                        ?.value['object_name'],
                                                    slug: addRbacFormKey
                                                        .currentState
                                                        ?.value['slug'],
                                                    shorthand: addRbacFormKey
                                                        .currentState
                                                        ?.value['shorthand'],
                                                    fontawesomeIcon: null,
                                                    createdAt: null,
                                                    updatedAt: null,
                                                    createdBy: null,
                                                    updatedBy: null);
                                              }
                                              setState(() {
                                                state.modules
                                                    .insert(0, newModule!);
                                              });
                                              moduleFocusNode.unfocus();
                                              Navigator.pop(context);
                                            },
                                          ));
                                    }),
                                    const SizedBox(
                                      height: 12,
                                    ),
                                    //// Permission

                                    StatefulBuilder(
                                        builder: (context, setState) {
                                      return SizedBox(
                                        width: double.infinity,
                                        child: Container(
                                          padding: const EdgeInsets.all(8),
                                          decoration: BoxDecoration(
                                              borderRadius:
                                                  BorderRadius.circular(5),
                                              border: Border.all(
                                                  color: Colors.grey)),
                                          child: Row(
                                            children: [
                                              Expanded(
                                                child: MultiSelectDropDown(
                                                  onOptionSelected:
                                                      (List<ValueItem>
                                                          selectedOptions) {
                                                    setState(() {
                                                      valueItemSelectedPermissions =
                                                          selectedOptions;
                                                    });
                                                  },
                                                  hint: "Permissions",
                                                  hintStyle: const TextStyle(
                                                      fontSize: 16,
                                                      color: Colors.grey),
                                                  padding:
                                                      const EdgeInsets.all(8),
                                                  options: valueItemPermission,
                                                  selectionType:
                                                      SelectionType.multi,
                                                  chipConfig: const ChipConfig(
                                                      wrapType:
                                                          WrapType.scroll),
                                                  dropdownHeight: 300,
                                                  optionTextStyle:
                                                      const TextStyle(
                                                          fontSize: 16),
                                                  selectedOptionIcon:
                                                      const Icon(
                                                          Icons.check_circle),
                                                ),
                                              ),
                                              const SizedBox(
                                                width: 6,
                                              ),
                                              IconButton(
                                                  ////Add Permission not the dialog add button
                                                  onPressed: () {
                                                    final addPermissionFormKey =
                                                        GlobalKey<FormState>();
                                                    showDialog(
                                                        context: context,
                                                        builder: (BuildContext
                                                            context) {
                                                          String? objectname;
                                                          String? slug;
                                                          String? shorthand;
                                                          return AlertDialog(
                                                              title: Row(
                                                                children: [
                                                                  Expanded(
                                                                    child:
                                                                        Container(
                                                                      child: !showAddOperations
                                                                          ? const Text(
                                                                              "Add new Permission")
                                                                          : const Text(
                                                                              "Add new Operation"),
                                                                    ),
                                                                  ),
                                                                  ////close button
                                                                  IconButton(
                                                                      onPressed:
                                                                          () {
                                                                        setState(
                                                                            () {
                                                                          showAddOperations =
                                                                              false;
                                                                        });
                                                                        Navigator.pop(
                                                                            context);
                                                                      },
                                                                      icon: const Icon(
                                                                          Icons
                                                                              .close))
                                                                ],
                                                              ),
                                                              content: StatefulBuilder(
                                                                  builder: (context,
                                                                      stateSetter) {
                                                                return showAddOperations
                                                                    ////add permission content if choice is in the choices
                                                                    ? FormBuilder(
                                                                        key:
                                                                            newOperationKey,
                                                                        child:
                                                                            Column(
                                                                          mainAxisSize:
                                                                              MainAxisSize.min,
                                                                          children: [
                                                                            FormBuilderTextField(
                                                                              onChanged: (value) {
                                                                                objectname = value!;
                                                                              },
                                                                              autovalidateMode: AutovalidateMode.always,
                                                                              validator: FormBuilderValidators.required(errorText: "This field is required"),
                                                                              name: "object_name",
                                                                              decoration: normalTextFieldStyle("Object name *", "Object name "),
                                                                            ),
                                                                            const SizedBox(
                                                                              height: 8,
                                                                            ),
                                                                            FormBuilderTextField(
                                                                              onChanged: (value) {
                                                                                slug = value!;
                                                                              },
                                                                              name: "slug",
                                                                              decoration: normalTextFieldStyle("Slug *", "Slug"),
                                                                            ),
                                                                            const SizedBox(
                                                                              height: 8,
                                                                            ),
                                                                            FormBuilderTextField(
                                                                              onChanged: (value) {
                                                                                shorthand = value!;
                                                                              },
                                                                              name: "shorthand",
                                                                              decoration: normalTextFieldStyle("Shorthand *", "Shorthand"),
                                                                            ),
                                                                            const SizedBox(
                                                                              height: 12,
                                                                            ),
                                                                            SizedBox(
                                                                                width: double.infinity,
                                                                                height: 50,
                                                                                /////Add new Operation submit button
                                                                                child: ElevatedButton(
                                                                                    style: mainBtnStyle(primary, Colors.transparent, second),
                                                                                    onPressed: () async {
                                                                                      if (newOperationKey.currentState!.saveAndValidate()) {
                                                                                        RBAC newOperation = RBAC(id: null, name: objectname, slug: slug, shorthand: shorthand, fontawesomeIcon: null, createdAt: null, updatedAt: null, createdBy: null, updatedBy: null);
                                                                                        stateSetter(() {
                                                                                          newOperations.add(newOperation);
                                                                                          valueItemOperation.insert(0, ValueItem(label: newOperation.name!, value: newOperation.name));
                                                                                          showAddOperations = false;
                                                                                        });
                                                                                      }
                                                                                    },
                                                                                    child: const Text("Add"))),
                                                                          ],
                                                                        ),
                                                                      )
                                                                    ////add permission content if choice is in the choices
                                                                    : Form(
                                                                        key:
                                                                            addPermissionFormKey,
                                                                        child:
                                                                            Column(
                                                                          mainAxisSize:
                                                                              MainAxisSize.min,
                                                                          children: [
                                                                            ////Object
                                                                            SizedBox(
                                                                                width: double.infinity,
                                                                                child:
                                                                                    ////Row ofr operation and add operation
                                                                                    Row(
                                                                                  children: [
                                                                                    ////Operations
                                                                                    Expanded(
                                                                                      child: MultiSelectDropDown(
                                                                                        onOptionSelected: (List<ValueItem> selectedOptions) {
                                                                                          stateSetter(() {
                                                                                            ////get operation ids
                                                                                            selectedValueItemOperation = selectedOptions;
                                                                                          });
                                                                                        },
                                                                                        borderColor: Colors.grey,
                                                                                        borderWidth: 1,
                                                                                        borderRadius: 5,
                                                                                        hint: "Operations",
                                                                                        hintStyle: const TextStyle(fontSize: 16, color: Colors.grey),
                                                                                        padding: const EdgeInsets.all(8),
                                                                                        options: valueItemOperation,
                                                                                        selectionType: SelectionType.multi,
                                                                                        chipConfig: const ChipConfig(wrapType: WrapType.wrap),
                                                                                        dropdownHeight: 300,
                                                                                        optionTextStyle: const TextStyle(fontSize: 16),
                                                                                        selectedOptionIcon: const Icon(Icons.check_circle),
                                                                                      ),
                                                                                    ),
                                                                                    const SizedBox(
                                                                                      width: 5,
                                                                                    ),
                                                                                    Container(
                                                                                      decoration: BoxDecoration(border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(5)),
                                                                                      child: IconButton(
                                                                                          ////Add Operation beside row button
                                                                                          onPressed: () {
                                                                                            stateSetter(() {
                                                                                              showAddOperations = true;
                                                                                            });
                                                                                          },
                                                                                          icon: const Icon(Icons.add)),
                                                                                    )
                                                                                  ],
                                                                                )),
                                                                            const SizedBox(
                                                                              height: 12,
                                                                            ),
                                                                            SearchField(
                                                                                itemHeight: 40,
                                                                                suggestionsDecoration: searchFieldDecoration(),
                                                                                suggestions: state.objects
                                                                                    .map((RBAC object) => SearchFieldListItem(object.name!,
                                                                                        item: object,
                                                                                        child: Padding(
                                                                                          padding: const EdgeInsets.symmetric(horizontal: 10),
                                                                                          child: ListTile(
                                                                                              title: Text(
                                                                                            object.name!,
                                                                                            overflow: TextOverflow.visible,
                                                                                          )),
                                                                                        )))
                                                                                    .toList(),
                                                                                validator: (module) {
                                                                                  if (module!.isEmpty) {
                                                                                    return "This field is required";
                                                                                  }
                                                                                  return null;
                                                                                },
                                                                                focusNode: objectFocusNode,
                                                                                searchInputDecoration: normalTextFieldStyle("Object *", "").copyWith(
                                                                                    suffixIcon: IconButton(
                                                                                  icon: const Icon(Icons.arrow_drop_down),
                                                                                  onPressed: () {
                                                                                    objectFocusNode.unfocus();
                                                                                  },
                                                                                )),
                                                                                onSuggestionTap: (object) {
                                                                                  stateSetter(() {
                                                                                    selectedObject = object.item;
                                                                                    objectFocusNode.unfocus();
                                                                                  });
                                                                                },
                                                                                ////Add new Object
                                                                                emptyWidget: AddRbac(
                                                                                  formKey: addRbacFormKey,
                                                                                  title: "Add Add Object",
                                                                                  onpressed: () {
                                                                                    if (addRbacFormKey.currentState!.saveAndValidate()) {
                                                                                      RBAC? newObject;

                                                                                      if (addRbacFormKey.currentState!.saveAndValidate()) {
                                                                                        newObject = RBAC(id: null, name: addRbacFormKey.currentState?.value['object_name'], slug: addRbacFormKey.currentState?.value['slug'], shorthand: addRbacFormKey.currentState?.value['shorthand'], fontawesomeIcon: null, createdAt: null, updatedAt: null, createdBy: null, updatedBy: null);
                                                                                      }
                                                                                      stateSetter(() {
                                                                                        state.objects.insert(0, newObject!);
                                                                                      });
                                                                                      objectFocusNode.unfocus();
                                                                                      Navigator.pop(context);
                                                                                    }
                                                                                  },
                                                                                )),
                                                                            const SizedBox(
                                                                              height: 20,
                                                                            ),
                                                                            SizedBox(
                                                                                width: double.infinity,
                                                                                height: 50,
                                                                                child: ElevatedButton(
                                                                                  onPressed: () {
                                                                                    ////Add Operation
                                                                                    if (addPermissionFormKey.currentState!.validate()) {
                                                                                      selectedValueItemOperation.forEach((e) {
                                                                                        setState(() {
                                                                                          // state.permission.insert(0, Permission(id: null, object: selectedObject!, operation: RBAC(id: null, name: e.label, slug: null, shorthand: null, fontawesomeIcon: null, createdAt: null, updatedAt: null, createdBy: null, updatedBy: null), createdAt: null, updatedAt: null, createdBy: null, updatedBy: null));
                                                                                          valueItemPermission.insert(0, ValueItem(label: "${selectedObject!.name} - ${e.label}"));
                                                                                          valueItemPermission = valueItemPermission;
                                                                                        });
                                                                                      });
                                                                                      Navigator.pop(context);
                                                                                      setState(() {});
                                                                                    }
                                                                                  },
                                                                                  style: mainBtnStyle(primary, Colors.transparent, second),
                                                                                  child: const Text("Submit"),
                                                                                ))
                                                                          ],
                                                                        ));
                                                              }));
                                                        });
                                                  },
                                                  icon: const Icon(Icons.add)),
                                            ],
                                          ),
                                        ),
                                      );
                                    }),
                                    const SizedBox(
                                      height: 12,
                                    ),
                                  ],
                                )),
                                SizedBox(
                                  height: 50,
                                  width: double.infinity,
                                  child: ElevatedButton(
                                      style: mainBtnStyle(
                                          primary, Colors.transparent, second),
                                      onPressed: () {
                                        if (formKey.currentState!
                                            .saveAndValidate()) {
                                          ////existing permission
                                          List<int> permissions =
                                              valueItemSelectedPermissions
                                                  .map((e) =>
                                                      int.parse(e.value!))
                                                  .toList();

                                          context.read<RbacBloc>().add(
                                              AssignedRbac(
                                                  assigneeId:
                                                      selectedWebUserId!,
                                                  assignerId: 63,
                                                  newPermissions: [],
                                                  permissionId: permissions,
                                                  selectedModule:
                                                      selectedModule,
                                                  selectedRole: selectedRole));
                                        }
                                        print(valueItemSelectedPermissions
                                            .length);
                                      },
                                      child: const Text("submit")),
                                )
                              ],
                            )),
                      );
                    }
                    if (state is RbacErrorState) {
                      return SomethingWentWrong(
                          message: state.message, onpressed: () {});
                    }
                    return Container();
                  },
                );
              }
              return Container();
            },
          ),
        ));
  }
}
