"use client";

import { Dispatch, MouseEvent, MutableRefObject, SetStateAction, useRef, useState } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { ChevronRight, MoreHorizontal } from "lucide-react";
// types
import { IIssueDisplayProperties, TIssue } from "@plane/types";
// ui
import { ControlLink, Tooltip } from "@plane/ui";
// components
import { MultipleSelectEntityAction } from "@/components/core";
import RenderIfVisible from "@/components/core/render-if-visible-HOC";
// constants
import { SPREADSHEET_SELECT_GROUP } from "@/constants/spreadsheet";
// helper
import { cn } from "@/helpers/common.helper";
// hooks
import { useIssueDetail, useProject } from "@/hooks/store";
import { TSelectionHelper } from "@/hooks/use-multiple-select";
import useOutsideClickDetector from "@/hooks/use-outside-click-detector";
import { usePlatformOS } from "@/hooks/use-platform-os";
// local components
import { TRenderQuickActions } from "../list/list-view-types";
import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC";
import { IssueColumn } from "./issue-column";

interface Props {
  displayProperties: IIssueDisplayProperties;
  isEstimateEnabled: boolean;
  quickActions: TRenderQuickActions;
  canEditProperties: (projectId: string | undefined) => boolean;
  updateIssue:
    | ((projectId: string | null, issueId: string, data: Partial<TIssue>) => Promise<void>)
    | undefined;
  portalElement: React.MutableRefObject<HTMLDivElement | null>;
  nestingLevel: number;
  issueId: string;
  isScrolled: MutableRefObject<boolean>;
  containerRef: MutableRefObject<HTMLTableElement | null>;
  issueIds: string[];
  spreadsheetColumnsList: (keyof IIssueDisplayProperties)[];
  spacingLeft?: number;
  selectionHelpers: TSelectionHelper;
}

export const SpreadsheetIssueRow = observer((props: Props) => {
  const {
    displayProperties,
    issueId,
    isEstimateEnabled,
    nestingLevel,
    portalElement,
    updateIssue,
    quickActions,
    canEditProperties,
    isScrolled,
    containerRef,
    issueIds,
    spreadsheetColumnsList,
    spacingLeft = 6,
    selectionHelpers,
  } = props;
  // states
  const [isExpanded, setExpanded] = useState<boolean>(false);
  // store hooks
  const { subIssues: subIssuesStore } = useIssueDetail();
  // derived values
  const subIssues = subIssuesStore.subIssuesByIssueId(issueId);
  const isIssueSelected = selectionHelpers.getIsEntitySelected(issueId);
  const isIssueActive = selectionHelpers.getIsEntityActive(issueId);

  return (
    <>
      {/* first column/ issue name and key column */}
      <RenderIfVisible
        as="tr"
        defaultHeight="calc(2.75rem - 1px)"
        root={containerRef}
        placeholderChildren={
          <td colSpan={100} className="border-[0.5px] border-transparent border-b-custom-border-200" />
        }
        classNames={cn("bg-custom-background-100 transition-[background-color]", {
          "group selected-issue-row": isIssueSelected,
          "border-[0.5px] border-custom-border-400": isIssueActive,
        })}
      >
        <IssueRowDetails
          issueId={issueId}
          displayProperties={displayProperties}
          quickActions={quickActions}
          canEditProperties={canEditProperties}
          nestingLevel={nestingLevel}
          spacingLeft={spacingLeft}
          isEstimateEnabled={isEstimateEnabled}
          updateIssue={updateIssue}
          portalElement={portalElement}
          isScrolled={isScrolled}
          isExpanded={isExpanded}
          setExpanded={setExpanded}
          spreadsheetColumnsList={spreadsheetColumnsList}
          selectionHelpers={selectionHelpers}
        />
      </RenderIfVisible>

      {isExpanded &&
        subIssues?.map((subIssueId: string) => (
          <SpreadsheetIssueRow
            key={subIssueId}
            issueId={subIssueId}
            displayProperties={displayProperties}
            quickActions={quickActions}
            canEditProperties={canEditProperties}
            nestingLevel={nestingLevel + 1}
            spacingLeft={spacingLeft + 12}
            isEstimateEnabled={isEstimateEnabled}
            updateIssue={updateIssue}
            portalElement={portalElement}
            isScrolled={isScrolled}
            containerRef={containerRef}
            issueIds={issueIds}
            spreadsheetColumnsList={spreadsheetColumnsList}
            selectionHelpers={selectionHelpers}
          />
        ))}
    </>
  );
});

interface IssueRowDetailsProps {
  displayProperties: IIssueDisplayProperties;
  isEstimateEnabled: boolean;
  quickActions: TRenderQuickActions;
  canEditProperties: (projectId: string | undefined) => boolean;
  updateIssue:
    | ((projectId: string | null, issueId: string, data: Partial<TIssue>) => Promise<void>)
    | undefined;
  portalElement: React.MutableRefObject<HTMLDivElement | null>;
  nestingLevel: number;
  issueId: string;
  isScrolled: MutableRefObject<boolean>;
  isExpanded: boolean;
  setExpanded: Dispatch<SetStateAction<boolean>>;
  spreadsheetColumnsList: (keyof IIssueDisplayProperties)[];
  spacingLeft?: number;
  selectionHelpers: TSelectionHelper;
}

const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
  const {
    displayProperties,
    issueId,
    isEstimateEnabled,
    nestingLevel,
    portalElement,
    updateIssue,
    quickActions,
    canEditProperties,
    isScrolled,
    isExpanded,
    setExpanded,
    spreadsheetColumnsList,
    spacingLeft = 6,
    selectionHelpers,
  } = props;
  // states
  const [isMenuActive, setIsMenuActive] = useState(false);
  // refs
  const cellRef = useRef(null);
  const menuActionRef = useRef<HTMLDivElement | null>(null);
  // router
  const { workspaceSlug, projectId } = useParams();
  // hooks
  const { getProjectIdentifierById } = useProject();
  const { getIsIssuePeeked, peekIssue, setPeekIssue } = useIssueDetail();
  const { isMobile } = usePlatformOS();

  const handleIssuePeekOverview = (issue: TIssue) =>
    workspaceSlug &&
    issue &&
    issue.project_id &&
    issue.id &&
    !getIsIssuePeeked(issue.id) &&
    setPeekIssue({
      workspaceSlug: workspaceSlug.toString(),
      projectId: issue.project_id,
      issueId: issue.id,
      nestingLevel: nestingLevel,
    });

  const { subIssues: subIssuesStore, issue } = useIssueDetail();

  const issueDetail = issue.getIssueById(issueId);

  const subIssueIndentation = `${spacingLeft}px`;

  useOutsideClickDetector(menuActionRef, () => setIsMenuActive(false));

  const customActionButton = (
    <div
      ref={menuActionRef}
      className={`flex items-center h-full w-full cursor-pointer rounded p-1 text-custom-sidebar-text-400 hover:bg-custom-background-80 ${
        isMenuActive ? "bg-custom-background-80 text-custom-text-100" : "text-custom-text-200"
      }`}
      onClick={() => setIsMenuActive(!isMenuActive)}
    >
      <MoreHorizontal className="h-3.5 w-3.5" />
    </div>
  );
  if (!issueDetail) return null;

  const handleToggleExpand = (e: MouseEvent<HTMLButtonElement>) => {
    e.stopPropagation();
    e.preventDefault();
    if (nestingLevel >= 3) {
      handleIssuePeekOverview(issueDetail);
    } else {
      setExpanded((prevState) => {
        if (!prevState && workspaceSlug && issueDetail && issueDetail.project_id)
          subIssuesStore.fetchSubIssues(workspaceSlug.toString(), issueDetail.project_id, issueDetail.id);
        return !prevState;
      });
    }
  };

  const disableUserActions = !canEditProperties(issueDetail.project_id ?? undefined);
  const subIssuesCount = issueDetail?.sub_issues_count ?? 0;
  const isIssueSelected = selectionHelpers.getIsEntitySelected(issueDetail.id);

  const canSelectIssues = !disableUserActions && !selectionHelpers.isSelectionDisabled;

  //TODO: add better logic. This is to have a min width for ID/Key based on the length of project identifier
  const keyMinWidth = (getProjectIdentifierById(issueDetail.project_id)?.length ?? 0 + 5) * 7;

  return (
    <>
      <td
        id={`issue-${issueId}`}
        ref={cellRef}
        tabIndex={0}
        className="sticky left-0 z-10 group/list-block bg-custom-background-100"
      >
        <ControlLink
          href={`/${workspaceSlug}/projects/${issueDetail.project_id}/issues/${issueId}`}
          target="_blank"
          onClick={() => handleIssuePeekOverview(issueDetail)}
          className={cn(
            "group clickable cursor-pointer h-11 w-[28rem] flex items-center text-sm after:absolute border-r-[0.5px] z-10 border-custom-border-200 bg-transparent group-[.selected-issue-row]:bg-custom-primary-100/5 group-[.selected-issue-row]:hover:bg-custom-primary-100/10",
            {
              "border-b-[0.5px]": !getIsIssuePeeked(issueDetail.id),
              "border border-custom-primary-70 hover:border-custom-primary-70":
                getIsIssuePeeked(issueDetail.id) && nestingLevel === peekIssue?.nestingLevel,
              "shadow-[8px_22px_22px_10px_rgba(0,0,0,0.05)]": isScrolled.current,
            }
          )}
          disabled={!!issueDetail?.tempId}
        >
          <div className="flex items-center gap-0.5 min-w-min py-2.5 pl-2">
            {/* select checkbox */}
            {projectId && canSelectIssues && (
              <Tooltip
                tooltipContent={
                  <>
                    Only issues within the current
                    <br />
                    project can be selected.
                  </>
                }
                disabled={issueDetail.project_id === projectId}
              >
                <div className="flex-shrink-0 grid place-items-center w-3.5 mr-1">
                  <MultipleSelectEntityAction
                    className={cn(
                      "opacity-0 pointer-events-none group-hover/list-block:opacity-100 group-hover/list-block:pointer-events-auto transition-opacity",
                      {
                        "opacity-100 pointer-events-auto": isIssueSelected,
                      }
                    )}
                    groupId={SPREADSHEET_SELECT_GROUP}
                    id={issueDetail.id}
                    selectionHelpers={selectionHelpers}
                    disabled={issueDetail.project_id !== projectId}
                  />
                </div>
              </Tooltip>
            )}

            {/* sub issues indentation */}
            <div style={nestingLevel !== 0 ? { width: subIssueIndentation } : {}} />

            <WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="key">
              <div className="relative flex cursor-pointer items-center text-center text-xs hover:text-custom-text-100">
                <p className={`flex font-medium leading-7`} style={{ minWidth: `${keyMinWidth}px` }}>
                  {getProjectIdentifierById(issueDetail.project_id)}-{issueDetail.sequence_id}
                </p>
              </div>
            </WithDisplayPropertiesHOC>

            {/* sub-issues chevron */}
            <div className="grid place-items-center size-4">
              {subIssuesCount > 0 && (
                <button
                  type="button"
                  className="grid place-items-center size-4 rounded-sm text-custom-text-400 hover:text-custom-text-300"
                  onClick={handleToggleExpand}
                >
                  <ChevronRight
                    className={cn("size-4", {
                      "rotate-90": isExpanded,
                    })}
                    strokeWidth={2.5}
                  />
                </button>
              )}
            </div>
          </div>

          <div className="flex items-center gap-2 justify-between h-full w-full pr-4 pl-1 truncate">
            <div className="w-full line-clamp-1 text-sm text-custom-text-100">
              <div className="w-full overflow-hidden">
                <Tooltip tooltipContent={issueDetail.name} isMobile={isMobile}>
                  <div
                    className="h-full w-full cursor-pointer truncate pr-4 text-left text-[0.825rem] text-custom-text-100 focus:outline-none"
                    tabIndex={-1}
                  >
                    {issueDetail.name}
                  </div>
                </Tooltip>
              </div>
            </div>
            <div className={`hidden group-hover:block ${isMenuActive ? "!block" : ""}`}>
              {quickActions({
                issue: issueDetail,
                parentRef: cellRef,
                customActionButton,
                portalElement: portalElement.current,
              })}
            </div>
          </div>
        </ControlLink>
      </td>
      {/* Rest of the columns */}
      {spreadsheetColumnsList.map((property) => (
        <IssueColumn
          key={property}
          displayProperties={displayProperties}
          issueDetail={issueDetail}
          disableUserActions={disableUserActions}
          property={property}
          updateIssue={updateIssue}
          isEstimateEnabled={isEstimateEnabled}
        />
      ))}
    </>
  );
});