import { type FC } from 'react';
import { FormProvider, type SubmitHandler, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';

import { LoadingButton } from '@mui/lab';
import { Stack, Typography } from '@mui/material';

import {
  type CompleteFile,
  type FileCompleterFunction,
} from '../../../types/attachments';
import { getInitials } from '../../../utils/user';
import Alert from '../../design-system/Alert';
import Avatar from '../../design-system/Avatar';
import CardContainer from '../../design-system/CardContainer';
import { type CardContainerProps } from '../../design-system/CardContainer/types';
import FormInputClassic from '../../design-system/Inputs/Classic/form';

import AddMediaButtons from './AddMediaButtons';
import { MAX_ATTACHED_SIZE } from './constants';
import EditMediaCarrousel from './EditMediaCarrousel';
import FilesCarrousel, { type FileCarrouselProps } from './FilesCarrousel';
import MediaSize from './MediaSize';

export type FieldValues = {
  body: string;
  files: CompleteFile[];
  media: CompleteFile[];
};

export type CreatePostProps = {
  profilePicture?: string;
  fullName: string;
  handlePost: SubmitHandler<FieldValues>;
  sx?: CardContainerProps['sx'];
  existingPost?: Partial<FieldValues>;
  onCancel?: () => void;
  uploadMedia?: FileCompleterFunction;
  uploadFile?: FileCompleterFunction;
  maxAttachedSize?: number;
  maxInputSize?: number;
  filesCarrouselProps?: FileCarrouselProps;
};

export const CreatePost: FC<CreatePostProps> = ({
  profilePicture,
  fullName,
  handlePost,
  sx,
  existingPost,
  onCancel,
  uploadMedia,
  uploadFile,
  maxAttachedSize = MAX_ATTACHED_SIZE,
  maxInputSize,
  filesCarrouselProps,
}) => {
  const { t } = useTranslation('material_hu_only');

  const form = useForm<FieldValues>({
    defaultValues: {
      body: existingPost?.body || '',
      files: existingPost?.files || [],
      media: existingPost?.media || [],
    },
  });

  const { media, files, body } = form.watch();

  const submit = form.handleSubmit(async values => {
    await handlePost(values);
    form.reset();
  });
  const { formState } = form;

  const isValidPost =
    (body.trim() || [...files, ...media].length) && // has body or attachments
    (!existingPost || formState.isDirty) && // something changed when editing
    [...files, ...media].every(file => file.attachment) && // all files are uploaded
    !formState.errors.files; // no file exceeds the limit

  const canUploadAttachments = !!(uploadMedia || uploadFile);
  const hasAttachments = [...files, ...media].length > 0;

  return (
    <FormProvider {...form}>
      <CardContainer
        fullWidth
        sx={sx}
        padding={24}
      >
        <Stack>
          <Stack sx={{ flexDirection: 'row', alignItems: 'center', gap: 1 }}>
            <Avatar
              src={profilePicture}
              text={getInitials(fullName)}
            />
            <Typography sx={{ flex: 1 }}>{fullName}</Typography>
            {canUploadAttachments && <MediaSize maxInMB={maxAttachedSize} />}
          </Stack>
          <FormInputClassic
            name="body"
            inputProps={{
              sx: {
                mt: 2,
                mb: 1.5,
              },
              multiline: true,
              maxLength: maxInputSize,
              minRows: 1,
              placeholder: t('posts.write_something'),
              hasCounter: false,
            }}
          />
          {hasAttachments && (
            <Stack sx={{ gap: 2, mb: 1.5 }}>
              <EditMediaCarrousel />
              <FilesCarrousel
                files={files}
                isEditable
                filesCarrouselProps={filesCarrouselProps}
              />
              {formState.errors.files && (
                <Alert
                  key={formState.errors.files.message} // to show it again after closing the alert
                  title={t('posts.file_size_exceeded', { maxAttachedSize })}
                  description={t('posts.file_size_exceeded_info')}
                  severity="error"
                  hasClose
                />
              )}
            </Stack>
          )}
          <Stack
            sx={{
              flexDirection: 'row',
              justifyContent: 'flex-end',
              '& .MuiStack-root': {
                flexDirection: 'row',
                gap: 1,
              },
            }}
          >
            {canUploadAttachments && (
              <AddMediaButtons
                uploadMedia={uploadMedia}
                uploadFile={uploadFile}
                maxAttachedSize={maxAttachedSize}
              />
            )}
            <Stack
              sx={{ ml: 'auto', '.MuiButton-root': { minWidth: 'unset' } }}
            >
              {!!onCancel && (
                <LoadingButton
                  variant="tertiary"
                  onClick={onCancel}
                >
                  {t('posts.cancel')}
                </LoadingButton>
              )}
              <LoadingButton
                variant="primary"
                onClick={submit}
                disabled={!isValidPost}
                loading={formState.isSubmitting}
                size="large"
              >
                {t(existingPost ? 'posts.edit' : 'posts.publish')}
              </LoadingButton>
            </Stack>
          </Stack>
        </Stack>
      </CardContainer>
    </FormProvider>
  );
};

export default CreatePost;
