import {useCallback, useMemo, useState, useEffect} from 'react';
import {Pressable, View, ScrollView} from 'react-native';
import {useTranslation} from 'react-i18next';
import {Image as ImageType} from 'react-native-image-crop-picker';
import {
  IconTrash,
  IconUpload,
  IconChevronDown,
  IconPhoto,
  IconMovie,
  IconFile,
  IconSearch,
} from '@tabler/icons-react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {
  Alert,
  Spinner,
  Chip,
  Typography,
  IconButton,
  InputTextArea,
} from '@components';
import {useGoBack} from '@hooks/useGoBack';
import {Navigation} from '@interfaces/navigation';
import {
  Attachment,
  ImageOrVideoAttachment,
  AttachmentType,
} from '@interfaces/attachments';
import {useAcknowledgedsStore} from '@modules/acknowledgement/stores/acknowledgedsStore';
import {
  AckUser,
  Acknowledgement,
  AcknowledgementCategory,
} from '@modules/acknowledgement/interfaces';
import useGetAcknowledgementsPointsLeftToGive from '@modules/acknowledgement/hooks/useGetAcknowledgementsPointsLeftToGive';
import {
  useCreateAcknowledgement,
  useGetAcknowledgement,
  useGetAckCategories,
} from '@modules/acknowledgement/hooks';
import {MAX_MESSAGE_LENGTH} from '@modules/acknowledgement/constants';
import {useUpdateAcknowledgement} from '@modules/acknowledgement/hooks/useUpdateAcknowledgement';
import {useUserId} from '@redux/selectors';
import {Screens} from '@shared/constants';
import {useTheme} from '@shared/theme';
import {
  getCompleteName,
  logImageCropped,
  uploadImage,
  uploadVideo,
  openCamera,
  openGallery,
} from '@shared/utils';
import {ERROR} from '@shared/strings';

import {styles} from './styles';
import {
  UsersDialog,
  MediaSelectionDialog,
  DeleteAttachmentDialog,
} from './components';

const PublishAcknowledgement = ({
  navigation,
  route,
}: Navigation<Screens.PUBLISH_ACKNOWLEDGEMENT>) => {
  const id = useUserId();
  const {theme, iconSizes} = useTheme();
  const {bottom} = useSafeAreaInsets();
  const {goBack} = useGoBack();
  const {acknowledgeds, setAcknowledgeds} = useAcknowledgedsStore();
  const {
    mutate: createAcknowledgementMutation,
    isPending: isLoadingCreateAcknowledgement,
  } = useCreateAcknowledgement();
  const {
    mutate: updateAcknowledgementMutation,
    isPending: isLoadingUpdateAcknowledgement,
  } = useUpdateAcknowledgement();
  const {t} = useTranslation();
  const ackIdParam = route.params?.updateAckId;
  const isAckUpdate = !!ackIdParam;

  const {data: acknowledgementsPointsLeftToGive, isFetching: isLoadingPoints} =
    useGetAcknowledgementsPointsLeftToGive(id, !isAckUpdate);

  const selected = useMemo(() => acknowledgeds || [], [acknowledgeds]);
  const hasSelections = selected.length > 0;
  const [showDialog, setShowDialog] = useState(false);
  const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false);
  const [userToDelete, setUserToDelete] = useState<Nullable<AckUser>>(null);
  const [selectedCategory, setSelectedCategory] =
    useState<Nullable<AcknowledgementCategory>>(null);
  const [message, setMessage] = useState('');

  const [showMediaModal, setShowMediaModal] = useState(false);

  const [attachments, setAttachments] = useState<Attachment[]>([]);
  const [loadingMultimedia, setLoadingMultimedia] = useState(false);

  const [
    showDeleteConfirmationAttachment,
    setShowDeleteConfirmationAttachment,
  ] = useState(false);
  const [attachmentToDelete, setAttachmentToDelete] =
    useState<Nullable<Attachment>>(null);

  const {isLoading: isLoadingCategories} = useGetAckCategories();

  const acknowledgedIds = useMemo(
    () => acknowledgeds?.map(acks => acks.id),
    [acknowledgeds],
  );

  const sectionContainerStyle = [
    styles.sectionContainer,
    {backgroundColor: theme.background.layout.tertiary},
  ];

  const {
    data: acknowledgementToUpdate,
    isLoading: isLoadingAcknowledgementToUpdate,
  } = useGetAcknowledgement(ackIdParam!, isAckUpdate);

  const acknowledgement = acknowledgementToUpdate as
    | Acknowledgement
    | undefined;

  useEffect(() => {
    // Handle category selection
    if (isAckUpdate && acknowledgement?.category) {
      // Update mode: use existing category
      setSelectedCategory(acknowledgement.category);
    } else if (route.params?.selectedCategory) {
      // Create mode: use selected category from previous screen
      setSelectedCategory(route.params.selectedCategory);
    }

    // Handle message and attachments for update mode
    if (isAckUpdate && acknowledgement?.body) {
      const {attachments: routeAttachments, body} = acknowledgement;
      setMessage(body);

      if (routeAttachments?.length > 0) {
        setAttachments(routeAttachments);
      }
    }
  }, [
    isAckUpdate,
    acknowledgement?.category,
    acknowledgement?.body,
    acknowledgement,
    route.params?.selectedCategory,
    setAcknowledgeds,
  ]);

  const onPressCategorySelector = useCallback(() => {
    navigation.navigate(Screens.SELECT_CATEGORY, {
      selectedCategoryId: selectedCategory?.id,
    });
  }, [navigation, selectedCategory?.id]);

  const onRemoveUser = useCallback(
    (userId: number) => () => {
      const newSelected = selected.filter(user => user.id !== userId);
      setAcknowledgeds(newSelected);
    },
    [setAcknowledgeds, selected],
  );

  const onDeleteUser = (user: AckUser) => () => {
    setUserToDelete(user);
    setShowDeleteConfirmation(true);
  };

  const onConfirmDelete = useCallback(() => {
    if (userToDelete) {
      const newSelected = selected.filter(user => user.id !== userToDelete.id);
      setAcknowledgeds(newSelected);
      setUserToDelete(null);
      setShowDeleteConfirmation(false);
    }
  }, [userToDelete, selected, setAcknowledgeds]);

  const onCancelDelete = () => {
    setUserToDelete(null);
    setShowDeleteConfirmation(false);
  };

  const onShowAllUsers = useCallback(() => {
    setShowDialog(true);
  }, []);

  const onCloseDialog = () => {
    setShowDialog(false);
  };

  const onPressSearchUsers = useCallback(
    () => navigation.navigate(Screens.SELECT_ACKNOWLEDGERS),
    [navigation],
  );

  const onLoadMedia = useCallback(() => {
    if (!loadingMultimedia) {
      setShowMediaModal(true);
    }
  }, [loadingMultimedia]);

  const onCloseMediaModal = useCallback(() => {
    setShowMediaModal(false);
  }, []);

  const addImage = useCallback(async (image: ImageType) => {
    setLoadingMultimedia(true);
    const {height, width, x, y} = image.cropRect!;
    const newImage = await uploadImage({...image, height, width});
    if (newImage !== ERROR) {
      setAttachments(prev => [...prev, newImage]);
      logImageCropped('PublishAcknowledgementHugo', x, y);
    }
    setLoadingMultimedia(false);
  }, []);

  const addVideo = useCallback(async (video: ImageOrVideoAttachment) => {
    setLoadingMultimedia(true);
    const newVideo = await uploadVideo(video);
    if (newVideo !== ERROR) {
      setAttachments(prev => [...prev, newVideo]);
    }
    setLoadingMultimedia(false);
  }, []);

  const onSelectVideo = useCallback(() => {
    onCloseMediaModal();
    openGallery({save: addVideo, options: {mediaType: 'video'}});
  }, [addVideo, onCloseMediaModal]);

  const onSelectImage = useCallback(() => {
    onCloseMediaModal();
    openGallery({save: addImage, options: {cropping: true}});
  }, [addImage, onCloseMediaModal]);

  const onSelectCamera = useCallback(() => {
    onCloseMediaModal();
    openCamera({save: addImage, options: {cropping: true}});
  }, [addImage, onCloseMediaModal]);

  const renderChips = useMemo(() => {
    return selected
      .slice(0, 1)
      .map(user => (
        <Chip
          key={user.id}
          text={getCompleteName(user)}
          showCloseIcon={selected.length === 1}
          onClose={onRemoveUser(user.id)}
          onPress={selected.length === 1 ? undefined : onShowAllUsers}
        />
      ));
  }, [selected, onRemoveUser, onShowAllUsers]);

  const onPressAttachment = useCallback(
    (attachmentParam: Attachment) => () => {
      navigation.navigate(Screens.VIEW_ATTACHMENT, {
        attachment: attachmentParam,
      });
    },
    [navigation],
  );
  const onPressDeleteShowDialog = useCallback(
    (attachmentParam: Attachment) => () => {
      setAttachmentToDelete(attachmentParam);
      setShowDeleteConfirmationAttachment(true);
    },
    [],
  );

  const onPublishAcknowledgement = useCallback(() => {
    if (isAckUpdate) {
      updateAcknowledgementMutation(
        {
          acknowledgementId: ackIdParam,
          data: {
            body: message,
            categoryId: selectedCategory?.id,
            images: attachments.filter(
              attachment => attachment.type === AttachmentType.IMAGE,
            ),
            videos: attachments.filter(
              attachment => attachment.type === AttachmentType.VIDEO,
            ),
          },
        },
        {
          onSuccess: goBack,
        },
      );
    } else {
      if (!selectedCategory?.id || !acknowledgedIds?.length || !message) {
        return;
      }
      const acknowledgementToCreate = {
        body: message,
        categoryId: selectedCategory?.id,
        attachments,
        acknowledgedIds: acknowledgedIds,
      };
      createAcknowledgementMutation(acknowledgementToCreate, {
        onSuccess: goBack,
      });
    }
  }, [
    selectedCategory,
    message,
    attachments,
    acknowledgedIds,
    createAcknowledgementMutation,
    updateAcknowledgementMutation,
    goBack,
    isAckUpdate,
    ackIdParam,
  ]);

  const onConfirmDeleteAttachment = useCallback(() => {
    if (attachmentToDelete) {
      setAttachments(prev =>
        prev.filter(att => att.url !== attachmentToDelete.url),
      );
      setShowDeleteConfirmationAttachment(false);
      setAttachmentToDelete(null);
    }
  }, [attachmentToDelete]);

  const onCancelDeleteAttachment = useCallback(() => {
    setShowDeleteConfirmationAttachment(false);
    setAttachmentToDelete(null);
  }, []);

  if (isLoadingPoints || isLoadingAcknowledgementToUpdate) {
    return (
      <View
        style={[
          styles.spinnerContainer,
          {backgroundColor: theme.background.layout.default},
        ]}>
        <Spinner />
      </View>
    );
  }

  const isPublishButtonDisabled =
    isLoadingPoints ||
    isLoadingCategories ||
    loadingMultimedia ||
    isLoadingCreateAcknowledgement ||
    isLoadingUpdateAcknowledgement ||
    !message ||
    (!isAckUpdate && !hasSelections) ||
    (!isAckUpdate && !selectedCategory) ||
    (!isAckUpdate && !acknowledgeds?.length);

  return (
    <View
      style={[
        styles.container,
        {backgroundColor: theme.background.layout.default},
      ]}>
      <ScrollView showsVerticalScrollIndicator={false}>
        {!isAckUpdate && (
          <>
            <View style={[styles.firstSection, sectionContainerStyle]}>
              <Alert
                title={t('acknowledgements.points_left_to_give', {
                  count: acknowledgementsPointsLeftToGive,
                })}
                variant="highLight"
              />
              <Typography weight="semiBold" style={styles.label}>
                {t('acknowledgements.who')}
              </Typography>
              <Pressable
                onPress={onPressSearchUsers}
                style={[
                  styles.inputButton,
                  styles.inputContainer,
                  {borderColor: theme.border.neutral.default},
                ]}>
                <IconSearch
                  size={iconSizes.x5}
                  color={theme.text.neutral.default}
                />
                <Typography color={theme.text.neutral.lighter} variant="s">
                  {t('acknowledgements.who_placeholder')}
                </Typography>
              </Pressable>
              {hasSelections && (
                <ScrollView
                  horizontal
                  showsHorizontalScrollIndicator={false}
                  contentContainerStyle={styles.chipsContainer}
                  style={styles.selectedUsersContainer}>
                  {renderChips}
                  {selected.length > 1 && (
                    <Chip
                      key={`${selected.length}-more`}
                      text={`+${selected.length - 1}`}
                      onPress={onShowAllUsers}
                    />
                  )}
                </ScrollView>
              )}
            </View>
            <View style={sectionContainerStyle}>
              <Typography weight="semiBold" style={styles.label}>
                {t('acknowledgements.select_category')}
              </Typography>
              <Pressable
                onPress={onPressCategorySelector}
                style={[
                  styles.categoriesContainer,
                  styles.inputContainer,
                  {borderColor: theme.border.neutral.default},
                ]}
                disabled={isLoadingCategories}>
                <Typography
                  variant="s"
                  numberOfLines={1}
                  style={styles.selectCategoryText}
                  color={
                    selectedCategory
                      ? theme.text.neutral.default
                      : theme.text.neutral.lighter
                  }>
                  {selectedCategory
                    ? selectedCategory.name
                    : t('acknowledgements.select_category')}
                </Typography>
                <IconChevronDown
                  size={iconSizes.x5}
                  color={
                    isLoadingCategories
                      ? theme.text.neutral.disabled
                      : theme.text.neutral.lighter
                  }
                />
              </Pressable>
            </View>
          </>
        )}

        <View style={[styles.messageContainer, sectionContainerStyle]}>
          <InputTextArea
            value={message}
            onChangeText={setMessage}
            maxLength={MAX_MESSAGE_LENGTH}
            label={t('acknowledgements.message')}
            placeholder={t('acknowledgements.message_placeholder')}
          />
        </View>
        <View style={sectionContainerStyle}>
          <Typography weight="semiBold" style={styles.label}>
            {t('acknowledgements.upload_media')}
          </Typography>
          <View
            style={[
              styles.uploadContainer,
              {borderColor: theme.border.neutral.default},
            ]}>
            {loadingMultimedia && (
              <View style={[styles.loadingContainer]}>
                <Spinner size={40} />
              </View>
            )}
            <Typography
              variant="xs"
              style={[styles.uploadText, loadingMultimedia && styles.opacity]}
              color={theme.text.neutral.lighter}>
              {t('acknowledgements.allowed_formats')}
            </Typography>
            <Pressable
              onPress={onLoadMedia}
              style={[
                styles.uploadButton,
                {borderColor: theme.border.neutral.brand},
                loadingMultimedia && styles.opacity,
              ]}>
              <Typography variant="s" color={theme.text.neutral.brand}>
                {t('acknowledgements.upload_file')}
              </Typography>
              <IconUpload
                size={iconSizes.x4}
                color={theme.text.neutral.brand}
              />
            </Pressable>
          </View>
          <View style={styles.fileListContainer}>
            {attachments.map(attachment => (
              <Pressable
                onPress={onPressAttachment(attachment)}
                key={attachment.id}
                style={[
                  styles.fileItem,
                  {borderColor: theme.border.neutral.default},
                ]}>
                <View style={styles.fileItemContent}>
                  <View
                    style={[
                      styles.fileIcon,
                      {backgroundColor: theme.background.layout.brand},
                    ]}>
                    {attachment.type === AttachmentType.IMAGE ? (
                      <IconPhoto size={20} color={theme.text.neutral.brand} />
                    ) : attachment.type === AttachmentType.VIDEO ? (
                      <IconMovie size={20} color={theme.text.neutral.brand} />
                    ) : (
                      <IconFile size={20} color={theme.text.neutral.brand} />
                    )}
                  </View>
                  <Typography
                    variant="s"
                    weight="semiBold"
                    style={styles.container}
                    color={theme.text.neutral.default}>
                    {attachment.name ||
                      t(
                        attachment.type === AttachmentType.IMAGE
                          ? 'general.image'
                          : 'general.video',
                      )}
                  </Typography>
                </View>
                <IconButton
                  Icon={IconTrash}
                  size="lg"
                  style={styles.deleteUserIcon}
                  onPress={onPressDeleteShowDialog(attachment)}
                  variant="flat"
                />
              </Pressable>
            ))}
          </View>
        </View>
      </ScrollView>
      <UsersDialog
        isVisible={showDialog}
        onClose={onCloseDialog}
        selected={selected}
        showDeleteConfirmation={showDeleteConfirmation}
        userToDelete={userToDelete}
        onDeleteUser={onDeleteUser}
        onConfirmDelete={onConfirmDelete}
        onCancelDelete={onCancelDelete}
      />
      <MediaSelectionDialog
        isVisible={showMediaModal}
        onClose={onCloseMediaModal}
        onSelectVideo={onSelectVideo}
        onSelectImage={onSelectImage}
        onSelectCamera={onSelectCamera}
      />

      <DeleteAttachmentDialog
        isVisible={showDeleteConfirmationAttachment}
        onClose={() => {
          setShowDeleteConfirmationAttachment(false);
          setAttachmentToDelete(null);
        }}
        onConfirmDelete={onConfirmDeleteAttachment}
        onCancel={onCancelDeleteAttachment}
      />

      <View
        style={[
          styles.footer,
          {
            backgroundColor: theme.background.layout.tertiary,
            borderTopColor: theme.border.neutral.default,
            paddingBottom: bottom,
          },
        ]}>
        <Pressable
          style={[
            styles.publishButton,
            {
              backgroundColor: isPublishButtonDisabled
                ? theme.button.background.primary.disabled
                : theme.button.background.primary.default,
            },
          ]}
          disabled={isPublishButtonDisabled}
          onPress={onPublishAcknowledgement}>
          {isLoadingCreateAcknowledgement || isLoadingUpdateAcknowledgement ? (
            <Spinner />
          ) : (
            <Typography
              weight="semiBold"
              color={
                isPublishButtonDisabled
                  ? theme.button.background.disabled.darker
                  : theme.text.neutral.inverted
              }
              align="center">
              {t(isAckUpdate ? 'general.save_changes' : 'general.publish')}
            </Typography>
          )}
        </Pressable>
        <Pressable style={styles.cancelButton} onPress={goBack}>
          <Typography
            weight="semiBold"
            color={theme.text.neutral.brand}
            align="center">
            {t('general.cancel')}
          </Typography>
        </Pressable>
      </View>
    </View>
  );
};

export default PublishAcknowledgement;
