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

import {
  buildWorkItemFilterExpressionFromConditions,
  workItemFiltersAdapter,
} from "@plane/shared-state";
import type { TWorkItemFilterCondition } from "@plane/shared-state";
import type {
  TExternalContourBoardFilter,
  TFilterValue,
  TWorkItemFilterExpression,
  TWorkItemFilterProperty,
} from "@plane/types";
import { COLLECTION_OPERATOR, COMPARISON_OPERATOR, EQUALITY_OPERATOR } from "@plane/types";
import { extractConditionsWithDisplayOperators, renderFormattedPayloadDate } from "@plane/utils";

export const EXTERNAL_CONTOUR_FILTER_PROPERTIES = [
  "project_id",
  "state_group",
  "state_id",
  "priority",
  "assignee_id",
  "created_by_id",
  "label_id",
  "target_date",
] as const satisfies TWorkItemFilterProperty[];

const toStringArray = (value: TFilterValue | TFilterValue[] | undefined): string[] => {
  if (value === undefined || value === null || value === "") return [];
  return (Array.isArray(value) ? value : [value]).map((item) => String(item)).filter(Boolean);
};

const toPayloadDate = (value: TFilterValue | undefined): string | undefined => {
  if (value === undefined || value === null || value === "") return undefined;
  return renderFormattedPayloadDate(value instanceof Date ? value : String(value)) ?? undefined;
};

export const buildExternalContourRichFilterExpression = (
  filters: Partial<TExternalContourBoardFilter>
): TWorkItemFilterExpression => {
  const conditions: TWorkItemFilterCondition[] = [];

  if (filters.counterparty_project_ids?.length) {
    conditions.push({
      property: "project_id",
      operator: COLLECTION_OPERATOR.IN,
      value: filters.counterparty_project_ids,
    });
  }

  if (filters.state_groups?.length) {
    conditions.push({
      property: "state_group",
      operator: COLLECTION_OPERATOR.IN,
      value: filters.state_groups,
    });
  }

  if (filters.state_ids?.length) {
    conditions.push({
      property: "state_id",
      operator: COLLECTION_OPERATOR.IN,
      value: filters.state_ids,
    });
  }

  if (filters.priority?.length) {
    conditions.push({
      property: "priority",
      operator: COLLECTION_OPERATOR.IN,
      value: filters.priority,
    });
  }

  if (filters.assignee_ids?.length) {
    conditions.push({
      property: "assignee_id",
      operator: COLLECTION_OPERATOR.IN,
      value: filters.assignee_ids,
    });
  }

  const authorIds = filters.requested_by_ids?.length ? filters.requested_by_ids : filters.created_by_ids;
  if (authorIds?.length) {
    conditions.push({
      property: "created_by_id",
      operator: COLLECTION_OPERATOR.IN,
      value: authorIds,
    });
  }

  if (filters.label_ids?.length) {
    conditions.push({
      property: "label_id",
      operator: COLLECTION_OPERATOR.IN,
      value: filters.label_ids,
    });
  }

  if (filters.target_date_exact) {
    conditions.push({
      property: "target_date",
      operator: EQUALITY_OPERATOR.EXACT,
      value: filters.target_date_exact,
    });
  } else if (filters.target_date_from && filters.target_date_to) {
    conditions.push({
      property: "target_date",
      operator: COMPARISON_OPERATOR.RANGE,
      value: [filters.target_date_from, filters.target_date_to],
    });
  }

  return buildWorkItemFilterExpressionFromConditions({ conditions }) ?? {};
};

export const buildExternalContourBoardFilters = (
  expression: TWorkItemFilterExpression
): Partial<TExternalContourBoardFilter> => {
  const internalExpression = workItemFiltersAdapter.toInternal(expression);
  if (!internalExpression) return {};

  const filters: Partial<TExternalContourBoardFilter> = {};
  const conditions = extractConditionsWithDisplayOperators(internalExpression);

  conditions.forEach((condition) => {
    switch (condition.property) {
      case "project_id":
        filters.counterparty_project_ids = toStringArray(condition.value);
        break;
      case "state_group":
        filters.state_groups = toStringArray(condition.value);
        break;
      case "state_id":
        filters.state_ids = toStringArray(condition.value);
        break;
      case "priority":
        filters.priority = toStringArray(condition.value);
        break;
      case "assignee_id":
        filters.assignee_ids = toStringArray(condition.value);
        break;
      case "created_by_id":
        filters.requested_by_ids = toStringArray(condition.value);
        break;
      case "label_id":
        filters.label_ids = toStringArray(condition.value);
        break;
      case "target_date":
        if (condition.operator === COMPARISON_OPERATOR.RANGE) {
          const [from, to] = toStringArray(condition.value);
          filters.target_date_from = toPayloadDate(from);
          filters.target_date_to = toPayloadDate(to);
        } else {
          filters.target_date_exact = toPayloadDate(
            Array.isArray(condition.value) ? condition.value[0] : condition.value
          );
        }
        break;
      default:
        break;
    }
  });

  return filters;
};
