import {useState} from 'react';
import {View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {ScrollView} from 'react-native-gesture-handler';
import {useMutation, useQueryClient} from '@tanstack/react-query';
import {ApprovalSteps, Approvers, ListRow, Title} from '@components';
import {Typography} from '@components/_core';
import {useSafeAreaBottomPadding} from '@hooks/useSafeAreaBottomPadding';
import {Navigation} from '@interfaces/navigation';
import {Attachment} from '@interfaces/attachments';
import StateTag from '@modules/timeOff/components/StateTag';
import {
  TimeOffRequestState,
  TimeOffStepState,
  AttachmentRequirement,
} from '@modules/timeOff/interfaces';
import {TIME_OFF_QUERY_KEYS} from '@modules/timeOff/constants';
import {updateTimeOffRequestAttachments} from '@modules/timeOff/services';
import Documentation from '@modules/timeOff/components/Documentation';
import Message from '@modules/timeOff/components/Message';
import {
  useGetApprovers,
  useGetRequestData,
  useTimeOffPanelStyle,
} from '@modules/timeOff/hooks';
import {getTimeUnitKey} from '@modules/timeOff/utils';
import DateRange from '@modules/timeOff/components/DateRange';
import Item from '@modules/timeOff/components/Item';
import {showSnackbar} from '@redux/dispatchers';
import {AMPLITUDE_EVENTS, Screens} from '@shared/constants';
import {
  getCompleteName,
  getDate,
  getTimeByLanguage,
  logAmplitudeEvent,
} from '@shared/utils';
import {useTheme} from '@shared/theme';

import ActionButtons from './components/ActionButtons';
import RequestDetailSk from './components/RequestDetailSk';
import {styles} from './styles';

const removeSeconds = (time: string) => {
  return time.substring(0, 5);
};

const RESOLUTION_DATE_KEY_BY_STATE: Partial<
  Record<TimeOffRequestState, string>
> = {
  [TimeOffRequestState.APPROVED]: 'time_off.approved_at',
  [TimeOffRequestState.REJECTED]: 'time_off.rejected_at',
  [TimeOffRequestState.CANCELLED]: 'time_off.cancelled_at',
};

function RequestDetail({
  route: {
    params: {calendarRowsFilters, id, role},
  },
}: Navigation<Screens.REQUEST_DETAIL>) {
  const {spacing, theme} = useTheme();
  const {t} = useTranslation();
  const queryClient = useQueryClient();

  const panelStyle = useTimeOffPanelStyle();
  const paddingBottom = useSafeAreaBottomPadding({bottom: spacing.x2});
  const [loadingAttachments, setLoadingAttachments] = useState(false);
  const {
    request,
    isLoadingRequest,
    isIssuer,
    isAdmin,
    canApproveOrReject,
    approvalSteps,
    currentStep,
    approvers,
    approversCount,
    isPending,
    showCancelButton,
    canEditRequest,
    canUploadAttachments,
    fromDateIsBeforeCreatedAt,
    showActionButtons,
  } = useGetRequestData({id, role});

  const {approversByStep, isLoadingApprovers} = useGetApprovers({
    enabled: !!approversCount && approversCount > 1 && !!currentStep,
    requestId: id,
    steps: approvalSteps,
  });

  const timeUnitKey = getTimeUnitKey(request?.policyType?.unit);
  const resolutionDateKey =
    request && RESOLUTION_DATE_KEY_BY_STATE[request.state];

  const {mutate: updateRequestAttachments} = useMutation({
    mutationFn: updateTimeOffRequestAttachments,
    onSuccess: (_, {attachments}) => {
      setLoadingAttachments(false);
      if (request && attachments.length > (request.attachments?.length ?? 0)) {
        logAmplitudeEvent(AMPLITUDE_EVENTS.TIME_OFF_DOCUMENTATION_ATTACHED, {
          source: 'REQUEST_DETAIL',
          requestState: request.state,
          requestId: request.id,
        });
      }
      queryClient.invalidateQueries({
        queryKey: TIME_OFF_QUERY_KEYS.request(id),
      });
      showSnackbar({title: t('time_off.request_successfully_updated')});
    },
    onError: () => {
      setLoadingAttachments(false);
      showSnackbar({
        title: t('time_off.error_updating_request'),
        variant: 'error',
      });
    },
  });

  const onUpdateAttachments = (attachments: Attachment[]) => {
    !!request?.id && updateRequestAttachments({attachments, id: request.id});
  };

  const onAddAttachments = (attachments: Attachment[]) => {
    const newAttachments = (request?.attachments || []).concat(attachments);
    onUpdateAttachments(newAttachments);
  };

  const onRemoveAttachment = (attachmentId: string) => {
    const newAttachments = (request?.attachments || []).filter(
      a => `${a.id}` !== attachmentId,
    );
    onUpdateAttachments(newAttachments);
  };

  return !request || isLoadingRequest ? (
    <RequestDetailSk />
  ) : (
    <>
      <ScrollView
        bounces={false}
        contentContainerStyle={[
          styles.container,
          !showActionButtons && {paddingBottom},
        ]}
        showsVerticalScrollIndicator={false}
        style={{backgroundColor: theme.background.layout.default}}>
        {request.edited && (
          <View style={panelStyle}>
            <Message
              description={t('time_off.request_edited_by_admin_description')}
              messageType="info"
              messages={[t('time_off.request_edited_by_admin')]}
            />
          </View>
        )}
        {request.creator.id !== request.issuer.id && (
          <View style={panelStyle}>
            <Message
              messages={[
                t('time_off.request_created_by', {
                  name: getCompleteName(request.creator),
                }),
              ]}
            />
          </View>
        )}
        {fromDateIsBeforeCreatedAt && (
          <View style={panelStyle}>
            <Message
              messageType="warning"
              messages={[t('time_off.period_before_current_date')]}
            />
          </View>
        )}
        {request.state === TimeOffRequestState.IN_PROGRESS &&
          approvalSteps.length > 1 && (
            <View style={panelStyle}>
              <ApprovalSteps approvalSteps={approvalSteps} />
            </View>
          )}
        {!isIssuer && request.issuer && (
          <View style={panelStyle}>
            <Item title={t('time_off.requested_by')}>
              <ListRow>
                <ListRow.Avatar
                  url={request.issuer.profilePicture}
                  name={request.issuer}
                />
                <ListRow.Title title={getCompleteName(request.issuer)} />
              </ListRow>
            </Item>
          </View>
        )}
        <View style={panelStyle}>
          <Item title={t('general.state')}>
            <StateTag
              state={isPending ? TimeOffStepState.PENDING : request.state}
            />
          </Item>
        </View>
        {!!request.resolutionReason && (
          <View style={panelStyle}>
            <Item title={t('time_off.reason')}>
              <Typography variant="s">{request.resolutionReason}</Typography>
            </Item>
          </View>
        )}
        <View style={panelStyle}>
          <Title
            size="s"
            title={request.policyType.name}
            titleNumberOfLines={2}
            topText={t('time_off.policy_type', {count: 1})}
          />
        </View>
        {!!request.resolutionDate && !!resolutionDateKey && (
          <View style={panelStyle}>
            <Title
              size="s"
              title={`${getDate(request.resolutionDate)}, ${getTimeByLanguage(
                request.resolutionDate,
              )}`}
              topText={t(resolutionDateKey)}
            />
          </View>
        )}
        {!!approversCount && !!currentStep && (
          <View style={panelStyle}>
            <Item
              title={t('time_off.responsible_for_response', {
                count: approversCount,
              })}>
              <Approvers
                approvers={approvers}
                approversByStep={approversByStep}
                approversCount={approversCount}
                isLoadingApprovers={isLoadingApprovers}
                isPending={isPending}
                steps={approvalSteps}
              />
            </Item>
          </View>
        )}
        <View style={panelStyle}>
          <Title
            size="s"
            title={getDate(request.createdAt)}
            topText={t('time_off.requested_on')}
          />
        </View>
        <View style={panelStyle}>
          <Title
            size="s"
            title={t(timeUnitKey, {count: request.amountRequested})}
            topText={t('time_off.amount_requested')}
          />
        </View>
        {request.amountAvailable !== null && (
          <View style={panelStyle}>
            <Title
              size="s"
              title={t(timeUnitKey, {count: request.amountAvailable})}
              topText={t('time_off.available_time')}
            />
          </View>
        )}
        <View style={panelStyle}>
          <Item title={t('time_off.request_period')}>
            <DateRange from={request.from} to={request.to} />
          </Item>
        </View>
        {request.from.time && request.to.time && (
          <View style={panelStyle}>
            <Title
              size="s"
              title={`${removeSeconds(request.from.time)} - ${removeSeconds(
                request.to.time,
              )}`}
              topText={t('time_off.request_period_time')}
            />
          </View>
        )}
        {(request.policyType.allowBalanceSale ||
          request.policyType.allowBalanceSaleBrazil) && (
          <View style={panelStyle}>
            <Item title={t('time_off.request_in_money')}>
              <Typography variant="s">{request.amountInMoney}</Typography>
            </Item>
          </View>
        )}
        {request.description && (
          <View style={panelStyle}>
            <Item title={t('time_off.observations')}>
              <Typography variant="s">{request.description}</Typography>
            </Item>
          </View>
        )}
        {request.substituteApprover && (
          <View style={panelStyle}>
            <Item title={t('time_off.substitute_approver.title')}>
              <ListRow>
                <ListRow.Avatar
                  name={request.substituteApprover}
                  url={request.substituteApprover.profilePicture}
                />
                <ListRow.Title
                  title={getCompleteName(request.substituteApprover)}
                />
              </ListRow>
            </Item>
          </View>
        )}
        {(canUploadAttachments || !!request.attachments?.length) && (
          <View style={panelStyle}>
            <Documentation
              canDownloadAttachments
              addAttachments={onAddAttachments}
              canUploadAttachments={canUploadAttachments}
              initialAttachments={request.attachments}
              instructions={request.policyType.attachmentInstructions}
              loadingAttachments={loadingAttachments}
              removeAttachment={onRemoveAttachment}
              setLoadingAttachments={setLoadingAttachments}
              showDeleteButton={
                request.policyType.attachmentRequirement !==
                  AttachmentRequirement.REQUIRED ||
                request.attachments?.length !== 1
              }
            />
          </View>
        )}
      </ScrollView>
      {showActionButtons && (
        <View
          style={[
            styles.footer,
            {
              backgroundColor: theme.background.layout.default,
              borderTopColor: theme.border.neutral.default,
              paddingBottom,
            },
          ]}>
          {isAdmin && canApproveOrReject && !isPending && (
            <Message
              description={t('time_off.resolve_request_as_admin_description')}
              messageType="info"
              messages={[t('time_off.resolve_request_as_admin')]}
              withClose
            />
          )}
          <ActionButtons
            approvalStepsCount={approvalSteps.length}
            requestId={request.id}
            stepId={currentStep?.id}
            policyTypeId={request.policyType.id}
            showCancelButton={showCancelButton}
            canEditRequest={canEditRequest}
            editIssuer={request.issuer}
            isIssuer={isIssuer}
            calendarRowsFilters={calendarRowsFilters}
          />
        </View>
      )}
    </>
  );
}

export default RequestDetail;
