import { type ReactNode } from 'react';

import {
  type CustomField,
  CustomFieldTypes,
  type MeInstance,
} from 'src/types/instance';
import { type TimeTrackingInfo, type User, UserStatus } from 'src/types/user';
import { insertIf } from 'src/utils/arrayUtils';
import { type TCustomFunction } from 'src/utils/i18n';
import {
  validateBirthdateRule,
  validateEmailRule,
  validatePasswordRule,
  validatePhoneNumberRule,
  validateRequiredStringRule,
  validateUrlRule,
  validateUsernameRule,
} from 'src/utils/validation';

import FormAutocomplete from 'src/components/FormInputs/FormAutocomplete';
import FormDatePicker from 'src/components/FormInputs/FormDatePicker';
import FormPhoneNumber from 'src/components/FormInputs/FormPhoneNumber';
import FormTextField from 'src/components/FormInputs/FormTextField';
import UsersAutocomplete from 'src/components/UsersAutocomplete';

import DepartmentsAutocomplete from './components/DepartmentsAutocomplete';
import PositionsAutocomplete from './components/PositionsAutocomplete';
import TimeTrackingAuthMethods from './components/TimeTrackingAccessMethods';
import UserInfo from './components/UserInfo';

export const getBasicInputs = (isNewUser: boolean, nameDisabled: boolean) => {
  const options = [
    {
      name: 'firstName',
      label: 'FIRST_NAME',
      rules: { validate: validateRequiredStringRule },
      columns: 1,
      required: true,
      disabled: nameDisabled,
    },
    {
      name: 'lastName',
      label: 'LAST_NAME',
      rules: { validate: validateRequiredStringRule },
      columns: 1,
      required: true,
      disabled: nameDisabled,
    },
    {
      name: 'nickname',
      label: 'NICK_NAME',
      columns: 2,
      required: false,
    },
    {
      name: 'employeeInternalId',
      label: 'ID',
      rules: { validate: validateUsernameRule },
      columns: 2,
      required: true,
    },
    ...insertIf(isNewUser, {
      name: 'password',
      label: 'PASSWORD',
      rules: { validate: validatePasswordRule },
      required: true,
      columns: 2,
    }),
    {
      name: 'email',
      label: 'EMAIL',
      rules: { validate: validateEmailRule },
      columns: 2,
      required: false,
    },
  ];
  return options;
};

export const SOCIAL_INPUTS = [
  {
    allow: 'allowLinkedin',
    name: 'linkedIn',
    label: 'LINKEDIN',
    type: 'url',
  },
  {
    allow: 'allowInstagram',
    name: 'instagram',
    label: 'INSTAGRAM',
    type: 'url',
  },
  {
    allow: 'allowFacebook',
    name: 'facebook',
    label: 'FACEBOOK',
    type: 'url',
  },
  {
    allow: 'allowTwitter',
    name: 'twitter',
    label: 'TWITTER',
    type: 'url',
  },
] as const;

type ProfileDataDateInput = {
  name: string;
  id?: string;
  fieldName?: string;
};

type ProfileDataDateParams = {
  input: ProfileDataDateInput;
  validateRules?: Parameters<typeof FormDatePicker>[0]['validateRules'];
  maxDate?: Date;
  disabled?: boolean;
};

type ProfileDataInputParams = {
  input: CustomField;
  disabled?: boolean;
};

export const PROFILE_DATA_INPUTS = {
  [CustomFieldTypes.DATE]: ({
    input,
    validateRules,
    maxDate,
    disabled = false,
  }: ProfileDataDateParams) => {
    const fieldName = input.fieldName || `profileData.${input.id}`;
    return (
      <FormDatePicker
        name={fieldName}
        datePickerProps={{
          label: input.name,
          maxDate,
          disabled,
        }}
        textFieldProps={{ variant: 'outlined', margin: 'dense', disabled }}
        validateRules={validateRules}
      />
    );
  },
  [CustomFieldTypes.STRING]: ({
    input,
    disabled = false,
  }: ProfileDataInputParams) => (
    <FormAutocomplete
      autocompleteProps={{
        freeSolo: true,
        options: input.suggestions,
        disabled,
      }}
      name={`profileData.${input.id}`}
      textFieldProps={{
        label: input.name,
        variant: 'outlined',
        margin: 'dense',
        inputProps: {
          maxLength: 300,
        },
        disabled,
      }}
    />
  ),
  [CustomFieldTypes.STRING_LIST]: ({
    input,
    disabled = false,
  }: ProfileDataInputParams) => (
    <FormAutocomplete
      autocompleteProps={{
        freeSolo: true,
        options: input.suggestions,
        multiple: true,
        disabled,
      }}
      name={`profileData.${input.id}`}
      textFieldProps={{
        label: input.name,
        variant: 'outlined',
        margin: 'dense',
        inputProps: {
          maxLength: 5000,
        },
        disabled,
      }}
    />
  ),
  [CustomFieldTypes.USER]: ({
    input,
    disabled = false,
  }: ProfileDataInputParams) => (
    <UsersAutocomplete
      name={`profileData.${input.id}`}
      textFieldProps={{
        label: input.name,
        variant: 'outlined',
        margin: 'dense',
        disabled,
      }}
      autocompleteProps={{ disabled }}
    />
  ),
  [CustomFieldTypes.USER_LIST]: ({
    input,
    disabled = false,
  }: ProfileDataInputParams) => (
    <UsersAutocomplete
      name={`profileData.${input.id}`}
      textFieldProps={{
        label: input.name,
        variant: 'outlined',
        margin: 'dense',
        disabled,
      }}
      autocompleteProps={{ multiple: true, disabled }}
    />
  ),
  [CustomFieldTypes.NUMBER]: ({
    input,
    disabled = false,
  }: ProfileDataInputParams) => (
    <FormTextField
      name={`profileData.${input.id}`}
      label={input.name}
      variant="outlined"
      type="number"
      margin="dense"
      disabled={disabled}
    />
  ),
  [CustomFieldTypes.NUMBER_LIST]: ({
    input,
    disabled = false,
  }: ProfileDataInputParams) => (
    <FormAutocomplete
      autocompleteProps={{
        freeSolo: true,
        multiple: true,
        disabled,
      }}
      name={`profileData.${input.id}`}
      textFieldProps={{
        label: input.name,
        variant: 'outlined',
        type: 'number',
        margin: 'dense',
        disabled,
      }}
    />
  ),
  [CustomFieldTypes.OPTION]: ({
    input,
    disabled = false,
  }: ProfileDataInputParams) => (
    <FormAutocomplete
      autocompleteProps={{
        options: input.options,
        disabled,
      }}
      name={`profileData.${input.id}`}
      textFieldProps={{
        label: input.name,
        variant: 'outlined',
        margin: 'dense',
        disabled,
      }}
    />
  ),
  [CustomFieldTypes.MULTIPLE_OPTION]: ({
    input,
    disabled = false,
  }: ProfileDataInputParams) => (
    <FormAutocomplete
      autocompleteProps={{
        options: input.options,
        multiple: true,
        disabled,
      }}
      name={`profileData.${input.id}`}
      textFieldProps={{
        label: input.name,
        variant: 'outlined',
        margin: 'dense',
        disabled,
      }}
    />
  ),
  PHOTOS_AND_VIDEOS: () => null,
  DOCUMENT: () => null,
};

export enum ProfileCategories {
  USER_INFO = 'USER_INFO',
  GENERAL = 'GENERAL',
  JOB = 'JOB',
  SOCIAL = 'SOCIAL',
  CUSTOM = 'CUSTOM',
}

export enum ConditionalCategories {
  TIME_TRACKING_ACCESS_METHODS = 'TIME_TRACKING_ACCESS_METHODS',
}

/** Context passed into each profile category renderer (excludes `disabled`). */
export type ProfileCategoryFieldsProps = {
  t: TCustomFunction;
  user?: User | null;
  instance?: MeInstance;
  instanceProfileFields?: CustomField[];
  timeTrackingInfo?: TimeTrackingInfo;
};

/**
 * Every category must take `disabled` as the first argument so new sections
 * cannot omit edit gating (see `EDIT_USER_INFO` / GeneralTab).
 */
export type ProfileCategoryRenderer = (
  disabled: boolean,
  fieldProps: ProfileCategoryFieldsProps,
) => ReactNode;

type ProfileCategoryInputsMap = Record<
  ProfileCategories | ConditionalCategories,
  ProfileCategoryRenderer
>;

export const PROFILE_CATEGORY_INPUTS: ProfileCategoryInputsMap = {
  [ProfileCategories.GENERAL]: (disabled, { t }) => (
    <>
      <PROFILE_DATA_INPUTS.DATE
        input={{ name: t('DATE_OF_BIRTH'), fieldName: 'birthdate' }}
        validateRules={validateBirthdateRule}
        maxDate={new Date()}
        disabled={disabled}
      />
      <FormPhoneNumber
        name="phoneNumber"
        textFieldProps={{
          label: t('PHONE_NUMBER'),
          margin: 'dense',
          variant: 'outlined',
          disabled,
        }}
        rules={{ validate: validatePhoneNumberRule }}
      />
    </>
  ),
  [ProfileCategories.JOB]: (disabled, { t, user }) => (
    <>
      <PROFILE_DATA_INPUTS.DATE
        input={{ name: t('HIRING_DATE'), fieldName: 'hiringDate' }}
        disabled={disabled}
      />
      <UsersAutocomplete
        name="boss"
        textFieldProps={{
          variant: 'outlined',
          label: t('BOSS'),
          margin: 'dense',
          disabled,
        }}
        autocompleteProps={{
          filterOptions: options => options.filter(u => u.id !== user?.id),
          disabled,
        }}
        potentialBossesId={user?.id}
      />
      <UsersAutocomplete
        name="reviewer"
        textFieldProps={{
          variant: 'outlined',
          label: t('REVIEWER'),
          margin: 'dense',
          disabled,
        }}
        autocompleteProps={{
          filterOptions: options => options.filter(u => u.id !== user?.id),
          disabled,
        }}
      />
      <DepartmentsAutocomplete
        textFieldProps={{
          variant: 'outlined',
          label: t('DEPARTMENT'),
          margin: 'dense',
          disabled,
        }}
        name="department"
        autocompleteProps={{ disabled }}
      />
      <PositionsAutocomplete
        textFieldProps={{
          variant: 'outlined',
          label: t('POSITION'),
          margin: 'dense',
          disabled,
        }}
        name="position"
        autocompleteProps={{ disabled }}
      />
    </>
  ),
  [ProfileCategories.SOCIAL]: (disabled, { t, instance }) => (
    <>
      {SOCIAL_INPUTS.map(
        input =>
          instance?.allowSocialNetworks?.[input.allow] && (
            <FormTextField
              {...input}
              label={t(input.label)}
              variant="outlined"
              key={input.name}
              margin="dense"
              rules={{ validate: validateUrlRule }}
              inputProps={{ maxLength: 255 }}
              disabled={disabled}
            />
          ),
      )}
    </>
  ),
  [ProfileCategories.CUSTOM]: (disabled, { instanceProfileFields = [] }) => (
    <>
      {instanceProfileFields.map(input => {
        const CustomFieldComponent = PROFILE_DATA_INPUTS[input.type];
        return (
          <CustomFieldComponent
            input={input}
            key={input.id}
            disabled={disabled}
          />
        );
      })}
    </>
  ),
  [ConditionalCategories.TIME_TRACKING_ACCESS_METHODS]: (
    disabled,
    { user, timeTrackingInfo },
  ) => {
    if (!user?.id || !timeTrackingInfo) return null;
    return (
      <TimeTrackingAuthMethods
        userId={user.id}
        settings={timeTrackingInfo}
        disabled={disabled}
      />
    );
  },
  [ProfileCategories.USER_INFO]: (disabled, { user }) => {
    if (!user || user.status !== UserStatus.DEACTIVATED) return null;
    return <UserInfo disabled={disabled} />;
  },
};

export const accordionFieldsForCategory = (
  instanceProfileFields: CustomField[],
) => ({
  [ProfileCategories.GENERAL]: ['birthdate', 'phoneNumber'],
  [ProfileCategories.JOB]: [
    'hiringDate',
    'boss',
    'reviewer',
    'department',
    'position',
  ],
  [ProfileCategories.SOCIAL]: ['linkedIn', 'instagram', 'facebook', 'twitter'],
  [ProfileCategories.CUSTOM]: instanceProfileFields.map(field => field.id),
  [ProfileCategories.USER_INFO]: [],
});
