import React, { useRef, useState } from "react";
import { Box, Chip, Grid, Icon, Typography } from "@mui/material";
import { useTags } from "../useTags";
import { EntityType } from "../types";
import { Icons } from "../../Icons";
import { Checkbox } from "../../Checkbox";
import { Area, AreaMenu, Menu, Tooltip, Input, Pill } from "../..";
import { cutNotes, getTagColor } from "../../../tools/tags";
import "./styles.scss";
import { useLocale } from "../../../hooks/useLocale";

const Selector = ({
  entity,
  value,
  disableUntaggedSelection,
  disableTagSelection,
  multiple,
  onChange,
  tags,
  units,
  drivers,
  landmarks,
  geofences,
  forms,
  subusers,
  assets,
  hideTagsWithoutEntities,
  messages,
  height,
  includeUnassignedDrivers,
  label,
  placeholder,
  setSearchText,
  values,
  allTags,
  onlyTags,
  showCount = false,
  inheritance = false,
  enableSelectAll = false,
  showOnlyEntity = false,
  menuStyle = {},
  handleIncludeInactiveDriversChange,
  includeInactiveDrivers,
}: any) => {
  const {
    expanded,
    getParentsTags,
    onExpand,
    defineMarginLeft,
    handleCheckboxChange,
    isItemDisabled,
    isItemChecked,
    isItemIndeterminate,
    isAllSelected,
    handleSelectAllChange,
    getEntities,
    getEntityList
  } = useTags({
    entity,
    value,
    disableUntaggedSelection,
    disableTagSelection,
    multiple,
    onChange,
    tags,
    units,
    drivers,
    landmarks,
    geofences,
    forms,
    subusers,
    assets,
    hideTagsWithoutEntities,
    onlyTags,
    inheritance,
    enableSelectAll,
  });
  const containerRef = useRef<HTMLDivElement>(null);
  const areaMenuRef = useRef<HTMLDivElement>(null);
  const instanceIdRef = useRef<string>(
    `selector-${Math.random().toString(36).substr(2, 9)}-${Date.now()}`
  );
  const parentsTags = getParentsTags();
  const entities = getEntities();
  const [searchTextValue, setSearchTextValue] = useState("");
  const [showIncludeInactiveDrivers, setShowIncludeInactiveDrivers] =
    useState(false);

  const filterEntitiesBySearchText = (entitiesList: any[]) => {
    if (!searchTextValue || searchTextValue.trim() === "") {
      return entitiesList;
    }
    const searchLower = searchTextValue.toLowerCase().trim();
    return entitiesList.filter((entity) => {
      const label = entity?.label || "";
      return label.toLowerCase().includes(searchLower);
    });
  };

  const filterTagsBySearchText = (tagsList: any[]) => {
    if (!searchTextValue || searchTextValue.trim() === "") {
      return tagsList;
    }
    const searchLower = searchTextValue.toLowerCase().trim();
    return tagsList.filter((tag) => {
      const label = tag?.label || "";
      return label.toLowerCase().includes(searchLower);
    });
  };

  const renderTagItem = (item: any, depth: number = 0) => {
    let hasChildren = false;
    if (item.hasChildren) {
      hasChildren = true;
    }
    if (item.entitiesCount > 0 && onlyTags === false) {
      hasChildren = true;
    }
    const isTag = item.name === EntityType.Tag;
    const marginLeft = defineMarginLeft(depth, isTag, hasChildren);
    const disabled = isItemDisabled(item);
    const isChecked = isItemChecked(item);
    const isIndeterminate = isItemIndeterminate(item);
    const isInactiveDriver =
      entity === "Driver" &&
      includeInactiveDrivers &&
      !isTag &&
      item.status === 0;

    return (
      <Box key={item.id}>
        <Box display="flex" alignItems="center" mt={1} style={{ marginLeft }}>
          {hasChildren && isTag && (
            <Icons
              name={
                expanded[item.id as keyof typeof expanded]
                  ? "arrow_drop_down"
                  : "arrow_right"
              }
              onClick={() => onExpand(item.id as number, item.disabled)}
              style={{ fontSize: 30, margin: "0px", cursor: "pointer" }}
            />
          )}
          <Grid item>
            <Checkbox
              checked={isChecked}
              value={isChecked ? "true" : "false"}
              isDisabled={disabled}
              id={`${instanceIdRef.current}-${item.id}`}
              onChange={() => handleCheckboxChange(item, searchTextValue?.trim() !== "")}
              isIndeterminate={isIndeterminate}
            />
          </Grid>
          {isTag && (
            <Grid item style={{ display: "flex" }}>
              <Icon
                style={{
                  fontSize: 18,
                  color: `#${item?.color}`,
                  marginRight: 6,
                }}
              >
                local_offer
              </Icon>
            </Grid>
          )}
          <Grid item xs zeroMinWidth>
            <Box display="flex" alignItems="center" gap={1}>
              <Tooltip
                placement="bottom"
                title={item?.id == -1 ? messages[item.label] : item.label}
              >
                <Typography noWrap>
                  {item?.id == -1 ? messages[item.label] : item.label}
                </Typography>
              </Tooltip>
            </Box>
          </Grid>
          {showCount && item?.entitiesCount > 0 && (
            <Grid item>
              <Typography variant="body2" color="text.secondary">
                {item.entitiesCount}
              </Typography>
            </Grid>
          )}
          {isInactiveDriver && (
            <Pill
              item={{
                id: "inactive",
                label: messages["inactive"] || "Inactive",
                color: "#9E9E9E",
              }}
              variant="outlined"
              size="dynamic"
              clickable={false}
              style={{ fontSize: "0.75rem", height: "20px" }}
            />
          )}
        </Box>

        {expanded[item.id]?.length > 0 &&
          expanded[item.id].map((childItem) => (
            <React.Fragment key={childItem.id}>
              {renderTagItem(childItem, depth + 1)}
            </React.Fragment>
          ))}
      </Box>
    );
  };

  const renderEntitiesItem = (item: any, isSearching: boolean = false) => {
    const disabled = isItemDisabled(item);
    const isChecked = isItemChecked(item);
    const isIndeterminate = isItemIndeterminate(item);
    const isInactiveDriver =
      entity === "Driver" && includeInactiveDrivers && item.status === 0;

    return (
      <Box key={item.id}>
        <Box display="flex" alignItems="center" mt={1}>
          <Grid item>
            <Checkbox
              checked={isChecked}
              value={isChecked ? "true" : "false"}
              isDisabled={disabled}
              id={`${instanceIdRef.current}-${item.id}`}
              onChange={() => handleCheckboxChange(item, searchTextValue?.trim() !== "")}
              isIndeterminate={isIndeterminate}
            />
          </Grid>
          <Grid item xs zeroMinWidth>
            <Box display="flex" alignItems="center" gap={1}>
              <Tooltip
                placement="bottom"
                title={item?.id == -1 ? messages[item.label] : item.label}
              >
                <Typography noWrap>
                  {item?.id == -1 ? messages[item.label] : item.label}
                </Typography>
              </Tooltip>
            </Box>
          </Grid>
          {showCount && item?.entitiesCount > 0 && (
            <Grid item>
              <Typography variant="body2" color="text.secondary">
                {item.entitiesCount}
              </Typography>
            </Grid>
          )}
          {isInactiveDriver && (
            <Pill
              item={{
                id: "inactive",
                label: messages["inactive"] || "Inactive",
                color: "#9E9E9E",
              }}
              variant="outlined"
              size="dynamic"
              clickable={false}
              style={{ fontSize: "0.75rem", height: "20px" }}
            />
          )}
        </Box>
      </Box>
    );
  };

  const renderParentContent = () => {
    const filteredTags = filterTagsBySearchText(parentsTags || []);
    const hasSearchText = searchTextValue && searchTextValue.trim() !== "";
    const tagsToShow =
      filteredTags.length === 0 && hasSearchText
        ? parentsTags || []
        : filteredTags;

    const showNoAvailableMessage = tagsToShow.length === 0 && !hasSearchText;

    return (
      <>
        {!showNoAvailableMessage ? (
          <Box width="100%">
            <AreaMenu
              id={"TagSelectorDropdown"}
              menuPlacement="bottom-start"
              clickAway={true}
              ref={areaMenuRef}
            >
              <Area>
                <div className="gtc-tag-picker-input-container">
                  <Input
                    type="text"
                    onChange={(value: string) => {
                      setSearchTextValue(value);
                      setSearchText?.(value);
                    }}
                    placeholder={placeholder}
                    value={searchTextValue}
                    icon="arrow_drop_down"
                    iconPosition="right"
                  />
                </div>
              </Area>
              <Menu>
                <Box
                  sx={{
                    ...menuStyle,
                    overflow: "hidden auto",
                  }}
                >
                  {enableSelectAll && onlyTags === true && searchTextValue?.trim() === "" && (
                    <Box ml="30px" mt={1} mb={1}>
                      <Checkbox
                        id={`${instanceIdRef.current}-select-all`}
                        checked={isAllSelected() ? true : false}
                        value={isAllSelected() ? "true" : "false"}
                        label={
                          messages["selectAllTags"] ||
                          "Seleccionar todos los tags"
                        }
                        onChange={handleSelectAllChange}
                      />
                    </Box>
                  )}
                  {tagsToShow?.map((tag) => (
                    <React.Fragment key={tag.id}>
                      {renderTagItem(tag, 0)}
                    </React.Fragment>
                  ))}
                </Box>
              </Menu>
            </AreaMenu>
            <div
              style={{
                marginTop: 8,
                maxHeight: 178,
                overflow: "hidden auto",
              }}
            >
              {values?.length > 0 &&
                values.map((value: any, index: number) => {
                  const currentTag = allTags?.find(
                    (tag: any) => tag?.id == value?.id
                  );
                  let label = cutNotes(value?.label, 15);
                  let currentColor = value?.color || currentTag?.color;
                  currentColor = currentColor?.replace("#", "");
                  let color = `#${getTagColor(currentColor)}`;

                  if (value?.id == -99) {
                    label = messages["tagPicker_allTagsAreSelected"];
                    color = "#007bff";
                  } else if (value?.id == -1) {
                    label = messages["untagged"];
                  }

                  return (
                    <Chip
                      label={label}
                      key={value.id}
                      style={{
                        color: "white",
                        backgroundColor: color,
                        marginBottom: 8,
                      }}
                      clickable={true}
                      deleteIcon={<Icon style={{ fontSize: 14 }}>close</Icon>}
                      onDelete={() => {
                        let newValues = values.filter(
                          (nv: any) => nv.id != value.id
                        );
                        if (onChange) onChange(newValues);
                      }}
                    />
                  );
                })}
            </div>
          </Box>
        ) : (
          <Typography variant="body1" color="red">
            {messages["noAvailableTags"]}
          </Typography>
        )}
      </>
    );
  };

  const renderEntitiesContent = () => {
    const filteredEntities = filterEntitiesBySearchText(entities || []);
    const entitiesToShow =
      filteredEntities.length === 0 &&
      searchTextValue &&
      searchTextValue.trim() !== ""
        ? entities || []
        : filteredEntities;

    const showNoAvailableMessage =
      entitiesToShow.length === 0 && !searchTextValue;

    return (
      <>
        {!showNoAvailableMessage ? (
          <>
            <AreaMenu
              id={"TagSelectorDropdown"}
              menuPlacement="bottom"
              clickAway={true}
              ref={areaMenuRef}
            >
              <Area>
                <div className="gtc-tag-picker-input-container">
                  <Input
                    type="text"
                    onChange={(value: string) => {
                      setSearchTextValue(value);
                      setSearchText?.(value);
                    }}
                    placeholder={placeholder}
                    value={searchTextValue}
                    icon="arrow_drop_down"
                    iconPosition="right"
                  />
                </div>
              </Area>
              <Menu>
                <Box
                  sx={{
                    ...menuStyle,
                    overflow: "hidden auto",
                  }}
                >
                  {enableSelectAll && onlyTags === true && (
                    <Box ml="30px" mt={1} mb={1}>
                      <Checkbox
                        id={`${instanceIdRef.current}-select-all`}
                        checked={isAllSelected() ? true : false}
                        value={isAllSelected() ? "true" : "false"}
                        label={
                          messages["selectAllTags"] ||
                          "Seleccionar todos los tags"
                        }
                        onChange={handleSelectAllChange}
                      />
                    </Box>
                  )}
                  {entitiesToShow?.map((entity) => (
                    <React.Fragment key={entity.id}>
                      {renderEntitiesItem(entity, searchTextValue?.trim() !== "")}
                    </React.Fragment>
                  ))}
                </Box>
              </Menu>
            </AreaMenu>
            <div
              style={{
                marginTop: 8,
                maxHeight: 178,
                overflow: "hidden auto",
              }}
            >
              {values?.length > 0 &&
                values.map((value: any, index: number) => {
                  const currentTag = allTags?.find(
                    (tag: any) => tag?.id == value?.id
                  );
                  let label = cutNotes(value?.label, 15);
                  let currentColor = value?.color || currentTag?.color;
                  currentColor = currentColor?.replace("#", "");
                  let color = `#${getTagColor(currentColor)}`;

                  if (value?.id == -99) {
                    label = messages["tagPicker_allTagsAreSelected"];
                    color = "#007bff";
                  } else if (value?.id == -1) {
                    label = messages["untagged"];
                  }

                  return (
                    <Chip
                      label={label}
                      key={value.id}
                      style={{
                        color: "white",
                        backgroundColor: color,
                        marginBottom: 8,
                      }}
                      clickable={true}
                      deleteIcon={<Icon style={{ fontSize: 14 }}>close</Icon>}
                      onDelete={() => {
                        let newValues = values.filter(
                          (nv: any) => nv.id != value.id
                        );
                        if (onChange) onChange(newValues);
                      }}
                    />
                  );
                })}
            </div>
          </>
        ) : (
          <Typography variant="body1" color="red">
            {messages["noAvailableTags"]}
          </Typography>
        )}
      </>
    );
  };


  return (
    <Box
      style={{
        height: height,
        maxHeight: height || 300,
        overflow: "hidden auto",
      }}
    >
      {entity === "Driver" && includeInactiveDrivers && (
        <Box>
          <Checkbox
            id={`${instanceIdRef.current}-unassigned-driver`}
            checked={showIncludeInactiveDrivers}
            value={showIncludeInactiveDrivers ? "true" : "false"}
            label={useLocale("include_inactive_drivers")}
            onChange={() => {
              setShowIncludeInactiveDrivers(!showIncludeInactiveDrivers);
              handleIncludeInactiveDriversChange &&
                handleIncludeInactiveDriversChange();
            }}
          />
        </Box>
      )}
      {label && <label className="input-normal-label">{label}</label>}
      <div ref={containerRef} className="gtc-tag-picker-dropdown-container">
        {showOnlyEntity ? renderEntitiesContent() : renderParentContent()}
      </div>
    </Box>
  );
};

export default Selector;
