/**
 * Copyright (c) 2023-present Plane Software, Inc. and contributors
 * SPDX-License-Identifier: AGPL-3.0-only
 * See the LICENSE file for details.
 */

import { useMemo } from "react";
import { Briefcase } from "lucide-react";
import { useTranslation } from "@plane/i18n";
import { Logo } from "@plane/propel/emoji-icon-picker";
import {
  DueDatePropertyIcon,
  LabelPropertyIcon,
  MembersPropertyIcon,
  PriorityIcon,
  PriorityPropertyIcon,
  StateGroupIcon,
  StatePropertyIcon,
  UserCirclePropertyIcon,
} from "@plane/propel/icons";
import type {
  IProject,
  IState,
  IIssueLabel,
  IUserLite,
  TExternalContourRequest,
  TFilterConfig,
  TWorkItemFilterProperty,
} from "@plane/types";
import { Avatar } from "@plane/ui";
import {
  getAssigneeFilterConfig,
  getCreatedByFilterConfig,
  getFileURL,
  getLabelFilterConfig,
  getPriorityFilterConfig,
  getProjectFilterConfig,
  getStateFilterConfig,
  getStateGroupFilterConfig,
  getTargetDateFilterConfig,
} from "@plane/utils";
import { useFiltersOperatorConfigs } from "@/plane-web/hooks/rich-filters/use-filters-operator-configs";

const sortByName = <T extends { name?: string | null; display_name?: string | null }>(items: T[]) =>
  [...items].sort((left, right) =>
    (left.display_name || left.name || "").localeCompare(right.display_name || right.name || "", "ru")
  );

const buildCounterpartyProjects = (requests: TExternalContourRequest[], projectId: string): IProject[] => {
  const projectMap = new Map<string, IProject>();

  requests.forEach((request) => {
    const project =
      request.direction === "incoming"
        ? request.source_project
        : request.target_project || request.issue.project_detail || null;

    if (!project?.id || project.id === projectId || projectMap.has(project.id)) return;

    projectMap.set(
      project.id,
      {
        id: project.id,
        name: project.name,
        logo_props: project.logo_props,
      } as IProject
    );
  });

  return sortByName(Array.from(projectMap.values()));
};

const buildStates = (requests: TExternalContourRequest[]): IState[] => {
  const stateMap = new Map<string, IState>();

  requests.forEach((request, index) => {
    const state = request.issue.state_detail;
    if (!state?.id || stateMap.has(state.id)) return;

    stateMap.set(
      state.id,
      {
        id: state.id,
        color: state.color,
        default: false,
        description: "",
        group: state.group,
        name: state.name,
        order: index + 1,
        project_id: request.issue.project_id || request.target_project?.id || request.source_project?.id || "",
        sequence: index + 1,
        workspace_id: "",
      } as IState
    );
  });

  return sortByName(Array.from(stateMap.values()));
};

const buildLabels = (requests: TExternalContourRequest[]): IIssueLabel[] => {
  const labelMap = new Map<string, IIssueLabel>();

  requests.forEach((request) => {
    request.issue.label_details?.forEach((label) => {
      if (!label.id || labelMap.has(label.id)) return;
      labelMap.set(
        label.id,
        {
          id: label.id,
          color: label.color,
          name: label.name,
          parent: null,
          project_id: request.issue.project_id || "",
          sort_order: 0,
          workspace_id: "",
        } as IIssueLabel
      );
    });
  });

  return sortByName(Array.from(labelMap.values()));
};

const buildAssignees = (requests: TExternalContourRequest[]): IUserLite[] => {
  const memberMap = new Map<string, IUserLite>();

  requests.forEach((request) => {
    request.issue.assignee_details?.forEach((assignee) => {
      if (!assignee.id || memberMap.has(assignee.id)) return;
      memberMap.set(
        assignee.id,
        {
          id: assignee.id,
          avatar_url: assignee.avatar_url,
          display_name: assignee.display_name,
        } as IUserLite
      );
    });
  });

  return sortByName(Array.from(memberMap.values()));
};

const buildRequesters = (requests: TExternalContourRequest[]): IUserLite[] => {
  const memberMap = new Map<string, IUserLite>();

  requests.forEach((request) => {
    const requesterId = request.requested_by?.id || request.requested_by_id || request.issue.created_by_detail?.id;
    const requesterName =
      request.requested_by?.display_name || request.requested_by_name || request.issue.created_by_detail?.display_name;

    if (!requesterId || !requesterName || memberMap.has(requesterId)) return;

    memberMap.set(
      requesterId,
      {
        id: requesterId,
        avatar_url: request.issue.created_by_detail?.avatar_url,
        display_name: requesterName,
      } as IUserLite
    );
  });

  return sortByName(Array.from(memberMap.values()));
};

type TUseExternalContoursFiltersConfigProps = {
  projectId: string;
  requests: TExternalContourRequest[];
  workspaceSlug: string;
};

export type TExternalContoursFiltersConfig = {
  areAllConfigsInitialized: boolean;
  configs: TFilterConfig<TWorkItemFilterProperty>[];
};

export const useExternalContoursFiltersConfig = (
  props: TUseExternalContoursFiltersConfigProps
): TExternalContoursFiltersConfig => {
  const { projectId, requests, workspaceSlug } = props;
  const { t } = useTranslation();
  const operatorConfigs = useFiltersOperatorConfigs({ workspaceSlug });

  const counterpartyProjects = useMemo(() => buildCounterpartyProjects(requests, projectId), [projectId, requests]);
  const states = useMemo(() => buildStates(requests), [requests]);
  const labels = useMemo(() => buildLabels(requests), [requests]);
  const assignees = useMemo(() => buildAssignees(requests), [requests]);
  const requesters = useMemo(() => buildRequesters(requests), [requests]);

  const configs = useMemo(
    () => [
      getProjectFilterConfig<TWorkItemFilterProperty>("project_id")({
        isEnabled: true,
        filterLabel: "Contour",
        filterIcon: Briefcase,
        projects: counterpartyProjects,
        getOptionIcon: (project) => <Logo logo={project.logo_props} size={12} />,
        ...operatorConfigs,
      }),
      getStateGroupFilterConfig<TWorkItemFilterProperty>("state_group")({
        isEnabled: true,
        filterIcon: StatePropertyIcon,
        getItemLabel: (stateGroupKey) => t(`workspace_projects.state.${stateGroupKey}`),
        getOptionIcon: (stateGroupKey) => <StateGroupIcon stateGroup={stateGroupKey} />,
        ...operatorConfigs,
      }),
      getStateFilterConfig<TWorkItemFilterProperty>("state_id")({
        isEnabled: true,
        filterIcon: StatePropertyIcon,
        getOptionIcon: (state) => <StateGroupIcon stateGroup={state.group} color={state.color} />,
        states,
        ...operatorConfigs,
      }),
      getPriorityFilterConfig<TWorkItemFilterProperty>("priority")({
        isEnabled: true,
        filterLabel: t("common.priority"),
        filterIcon: PriorityPropertyIcon,
        getItemLabel: (priorityKey) => (priorityKey === "none" ? t("common.none") : t(priorityKey)),
        getOptionIcon: (priority) => <PriorityIcon priority={priority} />,
        ...operatorConfigs,
      }),
      getAssigneeFilterConfig<TWorkItemFilterProperty>("assignee_id")({
        isEnabled: true,
        filterIcon: MembersPropertyIcon,
        members: assignees,
        getOptionIcon: (memberDetails) => (
          <Avatar
            name={memberDetails.display_name}
            src={getFileURL(memberDetails.avatar_url)}
            showTooltip={false}
            size="sm"
          />
        ),
        ...operatorConfigs,
      }),
      getCreatedByFilterConfig<TWorkItemFilterProperty>("created_by_id")({
        isEnabled: true,
        filterIcon: UserCirclePropertyIcon,
        members: requesters,
        getOptionIcon: (memberDetails) => (
          <Avatar
            name={memberDetails.display_name}
            src={getFileURL(memberDetails.avatar_url)}
            showTooltip={false}
            size="sm"
          />
        ),
        ...operatorConfigs,
      }),
      getLabelFilterConfig<TWorkItemFilterProperty>("label_id")({
        isEnabled: true,
        filterIcon: LabelPropertyIcon,
        labels,
        getOptionIcon: (color) => (
          <span className="flex size-2.5 flex-shrink-0 rounded-full" style={{ backgroundColor: color }} />
        ),
        ...operatorConfigs,
      }),
      getTargetDateFilterConfig<TWorkItemFilterProperty>("target_date")({
        isEnabled: true,
        filterIcon: DueDatePropertyIcon,
        ...operatorConfigs,
      }),
    ],
    [assignees, counterpartyProjects, labels, operatorConfigs, requesters, states, t]
  );

  return {
    areAllConfigsInitialized: true,
    configs,
  };
};
