import { type ReactNode } from 'react';

import { type TFunctionResult } from 'i18next';
import { type TableCellProps } from '@material-hu/mui/TableCell';

import type * as PxTypes from '@material-hu/components/composed-components/peopleExperience/types';

import { type Pagination } from 'src/types/services';
import {
  type Nullable,
  type ComparisionSurvey,
} from 'src/types/peopleExperience';

export type { Nullable, ComparisionSurvey };

// Survey

export enum CollaboratorSurveyStatus {
  PENDING = 'PENDING',
  FINISHED = 'FINISHED',
  UNCOMPLETED = 'UNCOMPLETED',
  IN_PROGRESS = 'IN_PROGRESS',
}

export enum ManagerSurveyStatus {
  ACTIVE = 'ACTIVE',
  FINISHED = 'FINISHED',
  IMPORTED = 'IMPORTED',
}

export type ManagerSurvey = {
  id: number;
  name: string;
  launchDate: Nullable<string>;
  description: Nullable<string>;
  status: ManagerSurveyStatus;
  allowViewManagerResults: boolean;
  finishDate: Nullable<string>;
  hasNPSQuestion: boolean;
  hasLikertQuestion: boolean;
  addBossInBossesFilter: boolean;
  addBossInDirectBossFilter: boolean;
  templates: Template[];
};

// Request params

export type FilterParams = {
  page?: number;
  limit?: number;
  q?: Nullable<string>;
};

export type CollaboratorSurveysReqParams = FilterParams & {
  status?: CollaboratorSurveyStatus;
};

export type ManagerSurveysParams = FilterParams & {
  status?: ManagerSurveyStatusFilter;
};

// Response
export type CollaboratorSurveryResData = {
  id: number;
  survey: ManagerSurvey;
  status: CollaboratorSurveyStatus;
};

export type StatusFilter = CollaboratorSurveyStatus | 'ALL';

export type StatusFilterOption = {
  label: string;
  value: StatusFilter;
};

export enum ErrorType {
  Access = 'ACCESS',
  RespondSurvey = 'RESPOND_SURVEY',
  Connection = 'CONNECTION',
}

export type AnswerOption = {
  id: number;
  label: string;
  subLabel: string | null;
};

export enum QuestionType {
  NPS = 'NPS',
  LIKERT = 'LIKERT',
  UNIQ_CHOICE = 'UNIQ_CHOICE',
  MULTI_CHOICE = 'MULTI_CHOICE',
  TEXT = 'TEXT',
}

export enum QuestionTemplateType {
  LIKERT = 'LIKERT',
  CHECKBOX = 'CHECKBOX',
  MULTIPLE_CHOICE = 'MULTIPLE_CHOICE',
  TEXT = 'TEXT',
  NPS = 'NPS',
}

export type Answer = string | number | number[] | boolean[];

export type Comment = string | null;

export type Topic = {
  id: number;
  title: string;
};

export type Question = {
  id: number;
  title: string;
  type: QuestionType;
  isMandatory?: boolean;
  allowComments?: boolean;
  options?: AnswerOption[];
  answer: QuestionResponse['answer'];
  answered: boolean;
  comment: Comment;
  choices: QuestionResponse['choices'];
};

export type SurveyFormValues = {
  answer: Answer | null;
  comment?: Comment;
};

export enum QuestionTypeResponse {
  RATING = 'RATING',
  TEXT = 'TEXT',
  CHECKBOX = 'CHECKBOX',
  MULTIPLE_CHOICE = 'MULTIPLE_CHOICE',
}

export enum QuestionSubtypeResponse {
  LIKERT = 'LIKERT',
  NPS = 'NPS',
}

export type QuestionResponse = {
  /** @deprecated Use `options` instead */
  choices: string[];
  commentableStatus: string;
  id: number;
  required: boolean;
  title: string;
  type: QuestionTypeResponse;
  subType: QuestionSubtypeResponse;
  answer: Answer | null;
  answered: boolean;
  comment: Comment;
  options: AnswerOption[];
};

export type Form = {
  description: string;
  questions: QuestionResponse[];
  title: string;
};

export type QuestionTemplate = {
  id: number;
  title: string;
  topics: Topic[];
  type: QuestionTemplateType;
};

export type FormTemplate = {
  questionTemplates: QuestionTemplate[];
};

export type Template = {
  formTemplate: FormTemplate;
};

export type SurveyDetailResponse = {
  description: string;
  name: string;
  id: ManagerSurvey['id'];
  finishDate: string | null;
  hasNPSQuestion: boolean;
  hasLikertQuestion: boolean;
  templates: Template[];
  addBossInBossesFilter: boolean;
  addBossInDirectBossFilter: boolean;
  anonymityThreshold: number | null;
};

export type SurveyResponse = {
  id: number;
  status: CollaboratorSurveyStatus;
  survey: SurveyDetailResponse;
  form: Form;
};

export type CategoryFilter = {
  label: string;
  value: any;
};

export type Column<TData> = {
  name: string;
  renderCell: (value: TData) => ReactNode;
  renderHeader: () => ReactNode | TFunctionResult;
  colSize?: number;
  skipEllipsis?: boolean;
};

export type ManagerSurveyStatusFilter = ManagerSurveyStatus | 'ALL';

export type TransformedSurvey = {
  id: number;
  title: string;
  description: string;
  status: CollaboratorSurveyStatus;
  finishDate: string | null;
  anonymityThreshold: number | null;
  questions: Question[];
};

export enum SortFilter {
  ASC = 'ASC',
  DESC = 'DESC',
}

export type Paginatable = {
  page: number;
  limit: number;
};

export type ManagerParticipationParams = Paginatable & {
  surveyId: ManagerSurvey['id'];
  q?: string;
  parentId: Nullable<number>;
  order?: SortFilter;
  dimension: SegmentType;
};

export type ParticipationListParams = ManagerParticipationParams & {
  depth: number;
};

export type ParticipationResponse = {
  total: number;
  pending: number;
};

export type ManagerParticipationResponse = Pagination<
  {
    id: number;
    totalReviews: number;
    completedReviews: number;
    title: string;
    subtitle: Nullable<string>;
    participationPercentage: number;
    hasChildren: boolean;
    childrenAmount: number;
  }[]
>;

export type BackupAnswerParams = {
  surveyId: ManagerSurvey['id'];
  questionId: QuestionResponse['id'];
  comment: Comment;
  answer?: Answer;
};

export type QuestionAnswer = {
  questionId: Question['id'];
  answer: Answer | null;
  comment: Comment;
};

export type RespondSurveyParams = {
  surveyId: ManagerSurvey['id'];
  questionAnswers: QuestionAnswer[];
  fillingTime: number;
};

export type RangeLegendMeta = {
  from: number;
  to: number;
  color: string;
};

type RenderDataCellProps<TData> = {
  rowData: TData;
  rowIndex: number;
  columnIndex: number;
};

export type HeatGridTableColumn<TData> = {
  name: string | number;
  element: ReactNode;
  renderDataCell: (params: RenderDataCellProps<TData>) => ReactNode;
  headerCellProps?: Partial<TableCellProps>;
  skipSkeleton?: boolean;
};

export type HeatGridTableData = Record<string, number> & {
  id: string | number;
  subject: { primary: string; secondary: string };
  total: number;
};

export enum SegmentType {
  SEGMENTATION_GROUPS = 'SEGMENTATION_GROUPS',
  BOSSES = 'BOSSES',
  DIRECT_BOSS = 'DIRECT_BOSS',
  AGE = 'AGE',
  SENIORITY = 'SENIORITY',
}

export type SegmentId = BaseSegmentId | string | number;

export type SegmentFilter = {
  id: SegmentId;
  type: SegmentType;
  title: string;
};

// Heatmap

export type SegmentationFilterParams = {
  excludeSegmentationItem?: string[];
  segmentationGroup?: string[];
  segmentationItem?: string[];
  ageId?: string[];
  seniorityId?: string[];
  excludeAgeId?: string[];
  excludeSeniorityId?: string[];
};

export type EnpsScoresParams = SegmentationFilterParams & {
  surveyId: ManagerSurvey['id'];
};

export type EnpsChartParams = EnpsScoresParams & {
  dimension?: SegmentType;
  parentId: number | null;
};

export type HeatmapReqParams = SegmentationFilterParams & {
  surveyId: number;
  dimension?: any;
  parentId?: SegmentFilter['id'];
};

export type HeatmapScoresReqParams = HeatmapReqParams & {
  dataSource: PxTypes.DataSource;
};

export enum HeatmapStatsType {
  QUESTIONS = 'QUESTIONS',
  TOPICS = 'TOPICS',
}

export enum StatKey {
  PROMOTERS = 'PROMOTERS',
  DETRACTORS = 'DETRACTORS',
  NEUTRALS = 'NEUTRALS',
}

export type Stats = Record<StatKey, number>;

export type EnpsBaseStats = {
  baseScoreDifference: number;
  count: number;
  missingComparison: boolean;
  passedThreshold: boolean;
  score: number;
  stats: Stats;
  statsPercentage: Stats;
  statsPercentageDifference: Stats;
};

export type EnpsScoresResponse = {
  baseStats: EnpsBaseStats;
  count: number;
  /** @deprecated */
  differenceStats: EnpsBaseStats[];
  passedThreshold: boolean;
  score: number;
  stats: Stats;
  statsPercentage: Stats;
};

export enum QuestionStatType {
  POSITIVE = 'POSITIVE',
  NEGATIVE = 'NEGATIVE',
  NEUTRAL = 'NEUTRAL',
}

export type QuestionStatChoicesStat = {
  amount: number;
  percentage: number;
  label: string;
  type: QuestionStatType;
};

export type TransformedChoicesStats = QuestionStatChoicesStat & {
  idx: number;
  value: number;
};

export type QuestionStatsResponse = {
  answersCount: number;
  commentsCount: Nullable<number>;
  stats: Record<string, number>;
  percentageStats: Record<string, number>;
  choices: string[];
  passedThreshold: boolean;
  score: Nullable<number>;
  baseScore: Nullable<number>;
  baseScoreDifference: Nullable<number>;
  choicesStats: QuestionStatChoicesStat[];
  type: QuestionTemplateType;
  scale: QuestionScaleResponse | null;
};

export type StringAnswer = { stringAnswer?: string };

export type IntegerAnswer = { integerAnswer?: number | number[] };

export type CommentsFilter = {
  idx: number;
  label: string;
  value: StringAnswer | IntegerAnswer;
  foreColor?: string;
  textColor?: string;
};

export type Dimension = {
  id: number;
  title: string;
};

export type QuestionSelectionFormState = {
  question: QuestionTemplate | null;
  dimension: Dimension | null;
  questionError: string | null;
};

export enum QuestionSelectionFormActionType {
  INIT_QUESTION = 'INIT_QUESTION',
  SET_QUESTION = 'SET_QUESTION',
  SET_DIMENSION = 'SET_DIMENSION',
}

export type QuestionSelectionFormAction =
  | {
      type: QuestionSelectionFormActionType.INIT_QUESTION;
      payload: QuestionTemplate;
    }
  | {
      type: QuestionSelectionFormActionType.SET_DIMENSION;
      payload: Dimension | null;
    }
  | {
      type: QuestionSelectionFormActionType.SET_QUESTION;
      payload: QuestionTemplate | null;
    };

export type QuestionAnswersParams = CommentsFilter['value'] & {
  formId: ManagerSurvey['id'];
  questionId: QuestionTemplate['id'];
  limit: number;
  page: number;
  isHighlighted?: boolean;
  hasComment?: boolean;
};

export enum ScoreTypeId {
  SCORE = 'score',
  DIFFERENCE = 'difference',
}

export type ScoreTypeFilter = {
  id: ScoreTypeId;
  title: string;
};

export enum BaseSegmentId {
  BOSS = 'direct-boss',
  TEAM = 'department',
}

export type QuestionAnswerResponse = {
  string: string;
  integer: number;
};

export type QuestionAnswersResponse = {
  answer: QuestionAnswerResponse;
  comment: string;
  id: number;
  isHighlighted: boolean;
};

/** eNps Chart */

export type EnpsSegment = {
  id: number;
  hasChildren: boolean;
  title: string;
  subtitle: string;
  score: number | null;
  passedThreshold: boolean;
  stats: EnpsSegment[];
  missingComparison?: boolean;
  baseScore: Nullable<number>;
  baseScoreAmount: Nullable<number>;
  baseScoreDifference: Nullable<number>;
};

export type EnpsHierarchy = EnpsSegment & {
  parentId: number | null;
};

export type EnpsChart = {
  stats: EnpsSegment[];
  hierarchy: EnpsHierarchy[];
};

export type LikertStats = {
  promoters: number;
  neutrals: number;
  detractors: number;
};

export type FavListIndexStatsResponse = {
  commentsAmount: number;
  score: number;
  respondentsAmount: number;
  answersAmount: number;
  passedThreshold: boolean;
  stats: LikertStats;
  baseScore: Nullable<number>;
  baseScoreDifference: Nullable<number>;
};

export type SelectQuestionStats = {
  rate: number;
  option: string;
};

export type FavBaseStatsResponse = {
  id: number;
  title: string;
  score: Nullable<number>;
  passedThreshold: boolean;
};

export type FavQuestionsStatsResponse = FavBaseStatsResponse & {
  answersAmount: number;
  commentsAmount: number;
  type: QuestionTemplateType;
  topic: Topic;
  hasLikertQuestion: boolean;
  scale: QuestionScaleResponse | null;
  baseScore: Nullable<number>;
  baseScoreDifference: Nullable<number>;
} & (
    | {
        type: QuestionTemplateType.LIKERT;
        metadata: Nullable<LikertStats>;
      }
    | {
        type:
          | QuestionTemplateType.CHECKBOX
          | QuestionTemplateType.MULTIPLE_CHOICE;
        metadata: Nullable<SelectQuestionStats>;
      }
    | {
        type: QuestionTemplateType.TEXT;
        metadata: null;
      }
  );

export type FavDimensionStatsResponse = FavBaseStatsResponse & {
  questionsCount: number;
  metadata: Nullable<LikertStats>;
  baseScore: Nullable<number>;
  baseScoreDifference: Nullable<number>;
};

export type FavDimensionIndexStatsResponse = {
  answersAmount: number;
  hasLikertQuestions: boolean;
  id: number;
  metadata: {
    detractors: number;
    neutrals: number;
    promoters: number;
  };
  passedThreshold: boolean;
  questionsCount: number;
  score: number;
  title: string;
  baseScore: Nullable<number>;
  baseScoreDifference: Nullable<number>;
};

export type FavDimensionStatsParams = {
  surveyId: ManagerSurvey['id'];
  page?: number;
  limit?: number;
};

export type FavQuestionsStatsParams = FavDimensionStatsParams & {
  topicId?: number;
};

export type QuestionStatsParams = SegmentationFilterParams & {
  formId: ManagerSurvey['id'];
  questionId: Question['id'];
};

export type FilterOptionResponse = {
  id: number;
  name: string;
};

export type SegmentationGroupsParams = {
  surveyId: ManagerSurvey['id'];
  page: number;
  limit: number;
};

export type SegmentationGroup = {
  id: number;
  name: string;
};

export type SegmentationGroupResponse = {
  id: number;
  name: string;
  type: string;
};

export type SegmentationItemsParams = {
  surveyId: ManagerSurvey['id'];
  groupId: number;
  searchText: string;
  limit?: number;
  page?: number;
  type?: string;
};

export type FavDimensionIndexStatsParams = SegmentationFilterParams & {
  surveyId: ManagerSurvey['id'];
  dimensionId: number;
};

export type FavListIndexParams = SegmentationFilterParams & {
  surveyId: ManagerSurvey['id'];
};

export type GetQuestionsResponse = {
  id: number;
  title: string;
  description: Nullable<string>;
  type: string;
  commentableStatus: string;
  origin: string;
  possibleAnswers: string[];
  answerRequired: boolean;
  topics?: Topic[];
  createdAt: string;
  updatedAt: string;
  status: string;
};

export type GetQuestionsParams = {
  q?: string;
  topicIds?: number[];
  ids?: number[];
  page?: number;
  limit?: number;
  offset?: number;
  surveyId?: ManagerSurvey['id'];
};

export type DimensionsParams = {
  q?: string;
  surveyId?: ManagerSurvey['id'];
  page?: number;
};

export enum ScaleRangeType {
  POSITIVE = 'POSITIVE',
  NEGATIVE = 'NEGATIVE',
  NEUTRAL = 'NEUTRAL',
}

export type QuestionScaleRange = {
  type: ScaleRangeType;
  range: {
    min: number;
    max: number;
  };
};

export enum LabelsConfig {
  TEXT_ONLY = 'TEXT_ONLY',
  NUMBER_ONLY = 'NUMBER_ONLY',
  TEXT_AND_NUMBER = 'TEXT_AND_NUMBER',
}

export type ScaleResponse = {
  ranges: QuestionScaleRange[];
  choices: string[];
  isNumeric: boolean;
  labelsConfig: LabelsConfig;
  numberOfChoices: number;
  labels?: { top?: string; bottom?: string };
};

export type QuestionScaleResponse = {
  id: number;
  name: string;
  createdAt: string;
  lastUsedAt: string | null;
  creator: {
    id: number;
    name: string;
  };
  scale: ScaleResponse;
};

export type TransformedManagerSurvey = Omit<ManagerSurvey, 'status'> & {
  status: {
    label: string;
    value: ManagerSurveyStatus;
  };
};
