import {
  ControlOutlined,
  FundProjectionScreenOutlined,
  MessageOutlined,
  QuestionCircleOutlined,
  SettingOutlined,
  SnippetsOutlined,
  TeamOutlined,
  WalletOutlined,
} from "@ant-design/icons";
import { Divider, Flex, Form, Menu, Select, Typography } from "antd";
import { useEffect, useState } from "react";
import { useLocation, useNavigate, useParams } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import {
  setIsSideMenuCollapsed,
  setSideMenuComponentFirstRender,
  sideMenuComponentFirstRender,
} from "./sideMenuSlice";
import { ItemType, MenuItemType } from "antd/es/menu/interface";
import {
  BreakpointLgWidth,
  BrowserTabSession,
  Constants,
} from "core/utils/utils";
import Search from "antd/es/input/Search";
import { MyContainer } from "shared/components/MyContainer";
import {
  addLessonContent,
  currentLessonId,
  lessonState,
} from "features/Lessons/LessonPageEditor/lessonPageEditorSlice";
import { Component, componentsGroups } from "features/Lessons/components";
import { darkMode, logoUrl } from "core/reducers/appSlice";
import { DndContext, DragOverlay } from "@dnd-kit/core";
import { createPortal } from "react-dom";
import { LessonState } from "core/types/lesson";
import { useForm } from "antd/es/form/Form";
import {
  useAddLessonContentMutation,
  useUpdateLessonStateMutation,
} from "core/services/lessons";
import webSocketService, {
  addWebSocketReconnectListener,
  removeWebSocketReconnectListener,
} from "core/services/websocketService";
import { WebSocketSendMessagesCmds } from "core/utils/webSocket";

export function SideMenuContent() {
  const location = useLocation();
  const [selectedKeys, setSelectedKeys] = useState("/");
  const [openKeys, setOpenKeys] = useState([""]);

  const dispatch = useDispatch();
  const componentFirstRender = useSelector(sideMenuComponentFirstRender);
  const appLogoUrl = useSelector(logoUrl);

  const navigate = useNavigate();

  const getFirstMenuItems = (): ItemType<MenuItemType>[] => {
    let items: ItemType<MenuItemType>[] = [];

    // overview

    let overviewGroup: ItemType<MenuItemType> = {
      key: "overviewGroup",
      label: "OVERVIEW",
      type: "group",
      children: [],
    };

    if (overviewGroup.children) {
      overviewGroup.children.push({
        key: Constants.ROUTE_PATHS.BOARD,
        label: "Board",
        icon: <FundProjectionScreenOutlined />,
      });

      overviewGroup.children.push({
        key: Constants.ROUTE_PATHS.LESSIONS.ROOT,
        label: "Lessons",
        icon: <SnippetsOutlined />,
      });
    }

    items.push(overviewGroup);

    // organization

    let organizationGroup: ItemType<MenuItemType> = {
      key: "organizationGroup",
      label: "ORGANIZATION",
      type: "group",
      children: [],
    };

    if (organizationGroup.children) {
      organizationGroup.children.push({
        key: Constants.ROUTE_PATHS.ORGANIZATION_TEAM,
        label: "Team",
        icon: <TeamOutlined />,
      });

      organizationGroup.children.push({
        key: Constants.ROUTE_PATHS.ORGANIZATION_ROLES,
        label: "Roles",
        icon: <ControlOutlined />,
      });

      organizationGroup.children.push({
        key: Constants.ROUTE_PATHS.ORGANIZATION_SETTINGS,
        label: "Settings",
        icon: <SettingOutlined />,
      });
    }

    items.push(organizationGroup);

    return items;
  };

  const getSecondMenuItems = (): ItemType<MenuItemType>[] => {
    let items: ItemType<MenuItemType>[] = [];

    // support

    items.push({
      key: Constants.ROUTE_PATHS.WHATS_NEW,
      label: "What's New",
      icon: <QuestionCircleOutlined />,
    });

    // feedback

    items.push({
      key: Constants.ROUTE_PATHS.SUGGEST_FEATURE,
      label: "Suggest a Feature",
      icon: <MessageOutlined />,
    });

    // payment plan

    items.push({
      key: Constants.ROUTE_PATHS.CONTACT_SUPPORT,
      label: "Contact Support",
      icon: <WalletOutlined />,
    });

    return items;
  };

  useEffect(() => {
    const pathname = location.pathname;

    setSelectedKeys(pathname);

    const subscribeTopicMessage = () => {
      webSocketService.send({
        Cmd: WebSocketSendMessagesCmds.SubscribeToTopic,
        Body: {
          topic: pathname,
          browserTabSession: BrowserTabSession,
        },
      });
    };

    subscribeTopicMessage();

    addWebSocketReconnectListener(subscribeTopicMessage);

    let path = pathname.split("/");

    if (path.length > 2) {
      // /store/:storeId/:subPage - open the store menu
      setOpenKeys([`/${path[1]}/${path[2]}`]);
    }

    // auto close sideMenu on mobile
    // this will prevent to auto close sideMenu on first render as the useEffects will be called after the first render
    if (componentFirstRender) {
      dispatch(setSideMenuComponentFirstRender(false));
    } else if (document.body.clientWidth < BreakpointLgWidth) {
      dispatch(setIsSideMenuCollapsed(true));
    }

    return () => removeWebSocketReconnectListener(subscribeTopicMessage);
  }, [location.pathname]);

  return (
    <div
      style={{
        display: "flex",
        justifyContent: "space-between",
        flexDirection: "column",
        height: "100%",
      }}
    >
      <div
        style={{
          display: "flex",
          flexDirection: "column",
          justifyContent: "space-between",
          overflowY: "hidden",
        }}
      >
        <div
          style={{
            display: "flex",
            flexDirection: "column",
            alignItems: "center",
            padding: 10,
          }}
        ></div>

        <div>
          <Flex justify="center" style={{ paddingBottom: 24, width: "100%" }}>
            {appLogoUrl !== null && (
              <img
                src={`${Constants.STATIC_CONTENT_ADDRESS}${
                  appLogoUrl || Constants.DEMO_LOGO_URL
                }`}
                alt="logo"
                style={{ height: 80 }}
              />
            )}
          </Flex>

          <Menu
            mode="inline"
            onClick={(item) => navigate(item.key)}
            theme="light"
            selectedKeys={[selectedKeys]}
            items={getFirstMenuItems()}
            openKeys={openKeys}
            onOpenChange={(openKeys) =>
              setOpenKeys(
                openKeys[openKeys.length - 1]
                  ? [openKeys[openKeys.length - 1]]
                  : []
              )
            }
          />
        </div>
      </div>

      <div>
        <Divider style={{ margin: 0 }} />

        <Menu
          selectable={true}
          selectedKeys={[selectedKeys]}
          mode="vertical"
          onClick={(item) => navigate(item.key)}
          items={getSecondMenuItems()}
        />
      </div>
    </div>
  );
}

export function SideMenuEditorContent() {
  // create is dragging useState
  const [isDragging, setIsDragging] = useState<String | null>(null);
  const { lessonId } = useParams();

  const [form] = useForm();

  const lnState = useSelector(lessonState);
  const currentLnId = useSelector(currentLessonId);

  const [updateLessonState] = useUpdateLessonStateMutation();

  useEffect(() => {
    form.setFieldsValue({
      state: lnState,
    });
  }, [lnState]);

  return (
    <Flex justify="space-between" vertical style={{ height: "100%" }}>
      <MyContainer>
        <Search
          placeholder="What would you like to insert?"
          style={{ paddingBottom: 16 }}
        />

        <DndContext
          onDragStart={(event) => {
            console.log("drag start", event.active.id);

            setIsDragging(event.active.id.toString());
          }}
          onDragEnd={(evnet) => {
            console.log("drag end", evnet.active.id);
            setIsDragging(null);
          }}
        >
          {componentsGroups.map((group, i) => (
            <div key={i}>
              <span>{group.category}</span>

              <Flex gap={16} wrap style={{ paddingTop: 16 }}>
                {group.components.map((component, i) => (
                  <DraggableCreateComponent key={i} component={component} />
                ))}
              </Flex>
            </div>
          ))}
          {createPortal(
            <DragOverlay>
              {isDragging
                ? (() => {
                    const comp = componentsGroups
                      .flatMap((group) => group.components)
                      .find((comp) => "draggable_" + comp.name === isDragging);
                    console.log("dragging", comp);
                    if (!comp) {
                      return null;
                    }

                    return (
                      <div style={{}}>
                        <CreateComponent component={comp} />
                      </div>
                    );
                  })()
                : null}
            </DragOverlay>,
            document.body
          )}
        </DndContext>
      </MyContainer>

      <div style={{ padding: 12 }}>
        <Form form={form} layout="vertical">
          <Form.Item label="Status" name="state" style={{ marginBottom: 0 }}>
            <Select
              style={{ width: "100%" }}
              onChange={async (value) => {
                console.log("state changed", value, lessonId);

                try {
                  await updateLessonState({
                    lessonId: currentLnId,
                    newState: value,
                  }).unwrap();
                } catch (err) {
                  console.log("error", err);
                }
              }}
            >
              <Select.Option value={LessonState.Published}>
                Published
              </Select.Option>
              <Select.Option value={LessonState.Draft}>Draft</Select.Option>
            </Select>
          </Form.Item>
        </Form>
      </div>
    </Flex>
  );
}

export function DraggableCreateComponent({
  component,
}: {
  component: Component;
}) {
  const dispatch = useDispatch();

  /*const { attributes, listeners, setNodeRef, transform, isDragging, active } =
    useDraggable({
      id: "draggable_" + component.name,
    });*/

  return (
    <>
      <div
        //ref={setNodeRef}
        //{...attributes}
        //{...listeners}
        style={
          {
            //transition: !isDragging ? "all 0.3s ease-out" : "none",
            //boxShadow: isDragging ? "0px 0px 10px 0px #00000040" : "none",
            //opacity: isDragging ? 0.25 : 1,
          }
        }
      >
        <CreateComponent component={component} />
      </div>
    </>
  );
}

function CreateComponent({ component }: { component: Component }) {
  const dispatch = useDispatch();
  const isDarkMode = useSelector(darkMode);

  const currentLnId = useSelector(currentLessonId);

  const [reqAddLessonContent] = useAddLessonContentMutation();

  return (
    <Flex
      vertical
      align="center"
      justify="center"
      style={{
        backgroundColor: !isDarkMode ? "#f0f2f5" : "#1f1f1f",
        height: 80,
        width: 80,
        cursor: "pointer",
      }}
      onClick={async () => {
        console.log("insert component", component.type);

        try {
          const res = await reqAddLessonContent({
            lessonId: currentLnId,
            type: component.type,
            data: component.defaultData || "",
          }).unwrap();

          console.log("add content", component);

          dispatch(
            addLessonContent({
              Id: res.Id,
              Type: component.type,
              Data: component.defaultData || "",
              Page: 1,
              Position: 1,
            })
          );
        } catch (err) {
          console.log("error", err);
        }
      }}
    >
      {component.thumbnail ? (
        <div>
          <img
            src={component.thumbnail}
            style={{
              width: 40,
              filter:
                isDarkMode && component.invertThumbnailAtDarkmode
                  ? "invert(1)"
                  : "invert(0)",
            }}
          />
        </div>
      ) : null}
      <Typography.Text style={{ fontSize: 12 }}>
        {component.name}
      </Typography.Text>
    </Flex>
  );
}

//console.log("insert component", component.type);
//dispatch(addLessonContent(component.type));
