// Flutter imports
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

// Syncrow project imports
import 'package:syncrow_web/pages/common/buttons/add_space_button.dart';
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/connection_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/subspace_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/blank_community_widget.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/community_structure_header_widget.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/dialogs/create_space_dialog.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/curved_line_painter.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/dialogs/duplicate_process_dialog.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_card_widget.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_container_widget.dart';
import 'package:syncrow_web/pages/spaces_management/helper/connection_helper.dart';
import 'package:syncrow_web/pages/spaces_management/helper/space_helper.dart';
import 'package:syncrow_web/pages/spaces_management/helper/tag_helper.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';

class CommunityStructureArea extends StatefulWidget {
  final CommunityModel? selectedCommunity;
  SpaceModel? selectedSpace;
  final List<ProductModel>? products;
  final ValueChanged<SpaceModel?>? onSpaceSelected;
  final List<CommunityModel> communities;
  final List<SpaceModel> spaces;
  final List<SpaceTemplateModel>? spaceModels;
  final List<Tag> projectTags;

  CommunityStructureArea(
      {this.selectedCommunity,
      this.selectedSpace,
      required this.communities,
      this.products,
      required this.spaces,
      this.onSpaceSelected,
      this.spaceModels,
      required this.projectTags});

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

class _CommunityStructureAreaState extends State<CommunityStructureArea> {
  double canvasWidth = 1000;
  double canvasHeight = 1000;
  List<SpaceModel> spaces = [];
  List<Connection> connections = [];
  late TextEditingController _nameController;
  bool isEditingName = false;
  late TransformationController _transformationController;

  @override
  void initState() {
    super.initState();
    spaces = widget.spaces.isNotEmpty ? flattenSpaces(widget.spaces) : [];
    connections =
        widget.spaces.isNotEmpty ? createConnections(widget.spaces) : [];
    _adjustCanvasSizeForSpaces();
    _nameController = TextEditingController(
      text: widget.selectedCommunity?.name ?? '',
    );
    realignTree();

    _transformationController = TransformationController();
    if (widget.selectedSpace != null) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _moveToSpace(widget.selectedSpace!);
      });
    }
  }

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

  @override
  void didUpdateWidget(covariant CommunityStructureArea oldWidget) {
    super.didUpdateWidget(oldWidget);

    if (oldWidget.spaces != widget.spaces) {
      setState(() {
        spaces = widget.spaces.isNotEmpty ? flattenSpaces(widget.spaces) : [];
        connections =
            widget.spaces.isNotEmpty ? createConnections(widget.spaces) : [];
        _adjustCanvasSizeForSpaces();
        realignTree();
      });
    }

    if (widget.selectedSpace != oldWidget.selectedSpace &&
        widget.selectedSpace != null) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _moveToSpace(widget.selectedSpace!);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    if (widget.selectedCommunity == null) {
      return BlankCommunityWidget(
        communities: widget.communities,
      );
    }

    Size screenSize = MediaQuery.of(context).size;
    return Expanded(
        child: GestureDetector(
      onTap: () {
        _deselectSpace(context);
      },
      child: Container(
        decoration: const BoxDecoration(
          border: Border(
            left: BorderSide(color: ColorsManager.whiteColors, width: 1.0),
          ),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            CommunityStructureHeader(
              communities: widget.communities,
              communityName: widget.selectedCommunity?.name,
              community: widget.selectedCommunity,
              isSave: SpaceHelper.isSave(spaces),
              isEditingName: isEditingName,
              nameController: _nameController,
              onSave: _saveSpaces,
              selectedSpace: widget.selectedSpace,
              onDelete: _onDelete,
              onDuplicate: () => {_onDuplicate(context)},
              onEdit: () => {_showEditSpaceDialog()},
              onEditName: () {
                setState(() {
                  isEditingName = !isEditingName;
                  if (isEditingName) {
                    _nameController.text = widget.selectedCommunity?.name ?? '';
                  }
                });
              },
              onNameSubmitted: (value) {
                context.read<SpaceManagementBloc>().add(
                      UpdateCommunityEvent(
                        communityUuid: widget.selectedCommunity!.uuid,
                        name: value,
                      ),
                    );
                setState(() {
                  widget.selectedCommunity?.name = value;
                  isEditingName = false;
                });
              },
            ),
            Flexible(
                child: Stack(
              children: [
                InteractiveViewer(
                  transformationController: _transformationController,
                  boundaryMargin: EdgeInsets.all(500),
                  minScale: 0.5,
                  maxScale: 3.0,
                  constrained: false,
                  child: Container(
                    width: canvasWidth,
                    height: canvasHeight,
                    child: Stack(
                      children: [
                        for (var connection in connections)
                          Opacity(
                            opacity: ConnectionHelper.isHighlightedConnection(
                                    connection, widget.selectedSpace)
                                ? 1.0
                                : 0.3, // Adjust opacity
                            child: CustomPaint(
                                painter: CurvedLinePainter([connection])),
                          ),
                        for (var entry in spaces.asMap().entries)
                          if (entry.value.status != SpaceStatus.deleted &&
                              entry.value.status != SpaceStatus.parentDeleted)
                            Positioned(
                              left: entry.value.position.dx,
                              top: entry.value.position.dy,
                              child: SpaceCardWidget(
                                index: entry.key,
                                onButtonTap: (int index, Offset newPosition) {
                                  _showCreateSpaceDialog(screenSize,
                                      position:
                                          spaces[index].position + newPosition,
                                      parentIndex: index,
                                      projectTags: widget.projectTags);
                                },
                                position: entry.value.position,
                                isHovered: entry.value.isHovered,
                                screenSize: screenSize,
                                onHoverChanged: _handleHoverChanged,
                                onPositionChanged: (newPosition) {
                                  _updateNodePosition(entry.value, newPosition);
                                },
                                buildSpaceContainer: (int index) {
                                  final bool isHighlighted =
                                      SpaceHelper.isHighlightedSpace(
                                          spaces[index], widget.selectedSpace);

                                  return Opacity(
                                      opacity: isHighlighted ? 1.0 : 0.3,
                                      child: SpaceContainerWidget(
                                        index: index,
                                        onTap: () {
                                          _selectSpace(context, spaces[index]);
                                        },
                                        icon: spaces[index].icon ?? '',
                                        name: spaces[index].name,
                                      ));
                                },
                              ),
                            ),
                      ],
                    ),
                  ),
                ),
                if (spaces.isEmpty)
                  Center(
                    child: AddSpaceButton(
                      onTap: () {
                        _showCreateSpaceDialog(screenSize,
                            canvasHeight: canvasHeight,
                            canvasWidth: canvasWidth,
                            projectTags: widget.projectTags);
                      },
                    ),
                  ),
              ],
            )),
          ],
        ),
      ),
    ));
  }

  void _updateNodePosition(SpaceModel node, Offset newPosition) {
    setState(() {
      node.position = newPosition;
      if (node.status != SpaceStatus.newSpace) {
        node.status = SpaceStatus.modified; // Mark as modified
      }
      if (node.position.dx >= canvasWidth - 200) {
        canvasWidth += 200;
      }
      if (node.position.dy >= canvasHeight - 200) {
        canvasHeight += 200;
      }
      if (node.position.dx <= 200) {
        double shiftAmount = 200;
        canvasWidth += shiftAmount;
        for (var n in spaces) {
          n.position = Offset(n.position.dx + shiftAmount, n.position.dy);
        }
      }
      if (node.position.dy < 0) {
        node.position = Offset(node.position.dx, 0);
      }
    });
  }

  void _adjustCanvasSizeForSpaces() {
    for (var space in spaces) {
      if (space.position.dx >= canvasWidth - 200) {
        canvasWidth = space.position.dx + 200;
      }

      if (space.position.dy >= canvasHeight - 200) {
        canvasHeight = space.position.dy + 200;
      }
    }
  }

  void _showCreateSpaceDialog(Size screenSize,
      {Offset? position,
      int? parentIndex,
      double? canvasWidth,
      double? canvasHeight,
      required List<Tag> projectTags}) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return CreateSpaceDialog(
          products: widget.products,
          spaceModels: widget.spaceModels,
          allTags:
              TagHelper.getAllTagValues(widget.communities, widget.spaceModels),
          parentSpace: parentIndex != null ? spaces[parentIndex] : null,
          projectTags: projectTags,
          onCreateSpace: (String name,
              String icon,
              List<SelectedProduct> selectedProducts,
              SpaceTemplateModel? spaceModel,
              List<SubspaceModel>? subspaces,
              List<Tag>? tags) {
            setState(() {
              // Set the first space in the center or use passed position
              Offset newPosition;
              if (parentIndex != null) {
                newPosition = getBalancedChildPosition(
                    spaces[parentIndex]); // Ensure balanced position
              } else {
                newPosition =
                    position ?? ConnectionHelper.getCenterPosition(screenSize);
              }

              SpaceModel newSpace = SpaceModel(
                  name: name,
                  icon: icon,
                  position: newPosition,
                  isPrivate: false,
                  children: [],
                  status: SpaceStatus.newSpace,
                  spaceModel: spaceModel,
                  subspaces: subspaces,
                  tags: tags);

              if (parentIndex != null) {
                SpaceModel parentSpace = spaces[parentIndex];
                parentSpace.internalId = spaces[parentIndex].internalId;
                newSpace.parent = parentSpace;
                final newConnection = Connection(
                  startSpace: parentSpace,
                  endSpace: newSpace,
                );
                connections.add(newConnection);
                newSpace.incomingConnection = newConnection;
                parentSpace.addOutgoingConnection(newConnection);
                parentSpace.children.add(newSpace);
              }
              spaces.add(newSpace);
              _updateNodePosition(newSpace, newSpace.position);
              realignTree();
            });
          },
        );
      },
    );
  }

  void _showEditSpaceDialog() {
    if (widget.selectedSpace != null) {
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return CreateSpaceDialog(
            products: widget.products,
            spaceModels: widget.spaceModels,
            name: widget.selectedSpace!.name,
            icon: widget.selectedSpace!.icon,
            projectTags: widget.projectTags,
            parentSpace: SpaceHelper.findSpaceByInternalId(
                widget.selectedSpace?.parent?.internalId, spaces),
            editSpace: widget.selectedSpace,
            currentSpaceModel: widget.selectedSpace?.spaceModel,
            tags: widget.selectedSpace?.tags,
            subspaces: widget.selectedSpace?.subspaces,
            isEdit: true,
            allTags: TagHelper.getAllTagValues(
                widget.communities, widget.spaceModels),
            onCreateSpace: (String name,
                String icon,
                List<SelectedProduct> selectedProducts,
                SpaceTemplateModel? spaceModel,
                List<SubspaceModel>? subspaces,
                List<Tag>? tags) {
              if (widget.selectedSpace!.isNoChangesSubmited(
                name,
                icon,
                spaceModel,
                subspaces,
                tags,
              )) {
                return;
              }
              setState(() {
                // Update the space's properties
                widget.selectedSpace!.name = name;
                widget.selectedSpace!.icon = icon;
                widget.selectedSpace!.spaceModel = spaceModel;
                widget.selectedSpace!.subspaces = subspaces;
                widget.selectedSpace!.tags = tags;

                if (widget.selectedSpace!.status != SpaceStatus.newSpace) {
                  widget.selectedSpace!.status =
                      SpaceStatus.modified; // Mark as modified
                }

                for (var space in spaces) {
                  if (space.internalId == widget.selectedSpace?.internalId) {
                    space.status = SpaceStatus.modified;
                    space.subspaces = subspaces;
                    space.tags = tags;
                    space.name = name;
                  }
                }
              });
            },
            key: Key(widget.selectedSpace!.name),
          );
        },
      );
    }
  }

  void _handleHoverChanged(int index, bool isHovered) {
    setState(() {
      spaces[index].isHovered = isHovered;
    });
  }

  List<SpaceModel> flattenSpaces(List<SpaceModel> spaces) {
    List<SpaceModel> result = [];
    Map<String, SpaceModel> idToSpace = {};

    void flatten(SpaceModel space) {
      if (space.status == SpaceStatus.deleted ||
          space.status == SpaceStatus.parentDeleted) {
        return;
      }
      result.add(space);
      idToSpace[space.internalId] = space;

      for (var child in space.children) {
        flatten(child);
      }
    }

    for (var space in spaces) {
      flatten(space);
    }

    for (var space in result) {
      if (space.parent != null) {
        space.parent = idToSpace[space.parent!.internalId];
      }
    }

    return result;
  }

  List<Connection> createConnections(List<SpaceModel> spaces) {
    List<Connection> connections = [];

    void addConnections(SpaceModel parent, String direction) {
      if (parent.status == SpaceStatus.deleted) return;

      for (var child in parent.children) {
        if (child.status == SpaceStatus.deleted) continue;

        connections.add(
          Connection(
            startSpace: parent,
            endSpace: child,
          ),
        );

        // Recursively process the child's children
        addConnections(child, direction);
      }
    }

    for (var space in spaces) {
      addConnections(space, "down");
    }

    return connections;
  }

  void _saveSpaces() {
    if (widget.selectedCommunity == null) {
      return;
    }

    List<SpaceModel> spacesToSave = spaces.where((space) {
      return space.status == SpaceStatus.newSpace ||
          space.status == SpaceStatus.modified ||
          space.status == SpaceStatus.deleted;
    }).toList();

    if (spacesToSave.isEmpty) {
      return;
    }

    String communityUuid = widget.selectedCommunity!.uuid;
    context.read<SpaceManagementBloc>().add(SaveSpacesEvent(
          context,
          spaces: spacesToSave,
          communityUuid: communityUuid,
        ));
  }

  void _onDelete() {
    if (widget.selectedSpace != null) {
      setState(() {
        for (var space in spaces) {
          if (space.internalId == widget.selectedSpace?.internalId) {
            space.status = SpaceStatus.deleted;
            _markChildrenAsDeleted(space);
          }
        }

        _removeConnectionsForDeletedSpaces();
      });
    }
  }

  void _markChildrenAsDeleted(SpaceModel parent) {
    for (var child in parent.children) {
      child.status = SpaceStatus.parentDeleted;

      _markChildrenAsDeleted(child);
    }
  }

  void _removeConnectionsForDeletedSpaces() {
    connections.removeWhere((connection) {
      return connection.startSpace.status == SpaceStatus.deleted ||
          connection.endSpace.status == SpaceStatus.deleted ||
          connection.startSpace.status == SpaceStatus.parentDeleted ||
          connection.endSpace.status == SpaceStatus.parentDeleted;
    });
  }

  void _moveToSpace(SpaceModel space) {
    final double viewportWidth = MediaQuery.of(context).size.width;
    final double viewportHeight = MediaQuery.of(context).size.height;

    final double dx = -space.position.dx + (viewportWidth / 2) - 400;
    final double dy = -space.position.dy + (viewportHeight / 2) - 300;

    _transformationController.value = Matrix4.identity()
      ..translate(dx, dy)
      ..scale(1.2);
  }

  void _selectSpace(BuildContext context, SpaceModel space) {
    context.read<SpaceManagementBloc>().add(
          SelectSpaceEvent(
              selectedCommunity: widget.selectedCommunity,
              selectedSpace: space),
        );
  }

  void _deselectSpace(BuildContext context) {
    context.read<SpaceManagementBloc>().add(
          SelectSpaceEvent(
              selectedCommunity: widget.selectedCommunity, selectedSpace: null),
        );
  }

  Offset getBalancedChildPosition(SpaceModel parent) {
    const double nodeWidth = 200;
    const double verticalGap = 180;

    if (parent.children.isEmpty) {
      // First child → exactly center
      return Offset(parent.position.dx, parent.position.dy + verticalGap);
    } else {
      // More children → arrange them spaced horizontally
      double totalWidth = (parent.children.length) * (nodeWidth + 60);
      double startX = parent.position.dx - (totalWidth / 2);

      double childX = startX + (parent.children.length * (nodeWidth + 60));
      return Offset(childX, parent.position.dy + verticalGap);
    }
  }

  void realignTree() {
    const double nodeWidth = 200;
    const double nodeHeight = 100;
    const double horizontalGap = 60;
    const double verticalGap = 180;
    const double rootGap = 400; // extra space between different roots

    double canvasRightEdge = 1000;
    double canvasBottomEdge = 1000;

    double calculateSubtreeWidth(SpaceModel node) {
      if (node.children.isEmpty) return nodeWidth;
      double totalWidth = 0;
      for (var child in node.children) {
        totalWidth += calculateSubtreeWidth(child) + horizontalGap;
      }
      return totalWidth - horizontalGap;
    }

    void layoutSubtree(SpaceModel node, double startX, double y) {
      double subtreeWidth = calculateSubtreeWidth(node);
      double centerX = startX + subtreeWidth / 2 - nodeWidth / 2;
      node.position = Offset(centerX, y);

      canvasRightEdge = max(canvasRightEdge, centerX + nodeWidth);
      canvasBottomEdge = max(canvasBottomEdge, y + nodeHeight);

      if (node.children.length == 1) {
        final child = node.children.first;
        layoutSubtree(child, centerX, y + verticalGap);
      } else {
        double childX = startX;
        for (var child in node.children) {
          double childWidth = calculateSubtreeWidth(child);
          layoutSubtree(child, childX, y + verticalGap);
          childX += childWidth + horizontalGap;
        }
      }
    }

    // ⚡ New: layout each root separately
    final List<SpaceModel> roots = spaces
        .where((s) =>
            s.parent == null &&
            s.status != SpaceStatus.deleted &&
            s.status != SpaceStatus.parentDeleted)
        .toList();

    double currentX = 100; // start some margin from left
    double currentY = 100; // top margin

    for (var root in roots) {
      layoutSubtree(root, currentX, currentY);
      double rootWidth = calculateSubtreeWidth(root);
      currentX += rootWidth + rootGap;
    }

    setState(() {
      canvasWidth = canvasRightEdge + 400;
      canvasHeight = canvasBottomEdge + 400;
    });
  }

  void _onDuplicate(BuildContext parentContext) {
    final screenWidth = MediaQuery.of(context).size.width;

    if (widget.selectedSpace != null) {
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            backgroundColor: ColorsManager.whiteColors,
            title: Text(
              "Duplicate Space",
              textAlign: TextAlign.center,
              style: Theme.of(context)
                  .textTheme
                  .headlineLarge
                  ?.copyWith(color: ColorsManager.blackColor),
            ),
            content: SizedBox(
              width: screenWidth * 0.4,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text("Are you sure you want to duplicate?",
                      textAlign: TextAlign.center,
                      style: Theme.of(context).textTheme.headlineSmall),
                  const SizedBox(height: 15),
                  Text("All the child spaces will be duplicated.",
                      textAlign: TextAlign.center,
                      style: Theme.of(context)
                          .textTheme
                          .bodyMedium
                          ?.copyWith(color: ColorsManager.lightGrayColor)),
                  const SizedBox(width: 15),
                ],
              ),
            ),
            actions: [
              Row(mainAxisAlignment: MainAxisAlignment.center, children: [
                SizedBox(
                  width: 200,
                  child: CancelButton(
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                    label: "Cancel",
                  ),
                ),
                const SizedBox(width: 10),
                SizedBox(
                  width: 200,
                  child: DefaultButton(
                    onPressed: () {
                      Navigator.of(context).pop();
                      showDialog(
                        context: context,
                        barrierDismissible: false,
                        builder: (BuildContext context) {
                          return DuplicateProcessDialog(
                            onDuplicate: () {
                              _duplicateSpace(widget.selectedSpace!);
                              _deselectSpace(parentContext);
                            },
                          );
                        },
                      );
                    },
                    backgroundColor: ColorsManager.secondaryColor,
                    borderRadius: 10,
                    foregroundColor: ColorsManager.whiteColors,
                    child: const Text('OK'),
                  ),
                ),
              ])
            ],
          );
        },
      );
    }
  }

  void _duplicateSpace(SpaceModel space) {
    setState(() {
      SpaceModel? parent = space.parent;

      SpaceModel duplicated = _deepCloneSpaceTree(space, parent: parent);

      duplicated.position =
          Offset(space.position.dx + 300, space.position.dy + 100);
      List<SpaceModel> duplicatedSubtree = [];
      void collectSubtree(SpaceModel node) {
        duplicatedSubtree.add(node);
        for (var child in node.children) {
          collectSubtree(child);
        }
      }

      collectSubtree(duplicated);
      spaces.addAll(duplicatedSubtree);

      if (parent != null) {
        parent.children.add(duplicated);

        final newConnection = Connection(
          startSpace: parent,
          endSpace: duplicated,
        );
        connections.add(newConnection);
        duplicated.incomingConnection = newConnection;
        parent.addOutgoingConnection(newConnection);
      }

      realignTree();
      connections = createConnections(spaces);
    });
  }

  SpaceModel _deepCloneSpaceTree(SpaceModel original, {SpaceModel? parent}) {
    final duplicatedName =
        SpaceHelper.generateUniqueSpaceName(original.name, spaces);

    final newSpace = SpaceModel(
      name: duplicatedName,
      icon: original.icon,
      position: original.position,
      isPrivate: original.isPrivate,
      children: [],
      status: SpaceStatus.newSpace,
      spaceModel: original.spaceModel,
      subspaces: original.subspaces,
      tags: original.tags,
      parent: parent,
    );

    for (var child in original.children) {
      final duplicatedChild = _deepCloneSpaceTree(child, parent: newSpace);
      newSpace.children.add(duplicatedChild);

      final newConnection = Connection(
        startSpace: newSpace,
        endSpace: duplicatedChild,
      );
      connections.add(newConnection);

      duplicatedChild.incomingConnection = newConnection;
      newSpace.addOutgoingConnection(newConnection);
    }

    return newSpace;
  }
}
