import { Button } from '@documenso/ui/primitives/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@documenso/ui/primitives/card';
import { DocumentDropzone } from '@documenso/ui/primitives/document-dropzone';

import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd';
import { msg } from '@lingui/core/macro';
import { Trans, useLingui } from '@lingui/react/macro';
import { FileWarningIcon, GripVerticalIcon, Loader2Icon, PencilIcon, XIcon } from 'lucide-react';

import { EnvelopeItemDeleteDialog } from '~/components/dialogs/envelope-item-delete-dialog';

import { EnvelopeEditorInvalidDirectTemplateAlert } from './envelope-editor-invalid-direct-template-alert';
import { EnvelopeEditorRecipientForm } from './envelope-editor-recipient-form';
import { EnvelopeItemTitleInput } from './envelope-editor-title-input';

import { useEnvelopeEditorUpload } from './use-envelope-editor-upload';

export const EnvelopeEditorUploadPage = () => {
  const { t } = useLingui();
  const {
    envelope,
    editorConfig,
    isEmbedded,
    navigateToStep,
    localFiles,
    replacingItemIdRef,
    openReplaceFilePicker,
    getReplaceInputProps,
    uploadConfig,
    envelopeItemPermissions,
    isCreatingEnvelopeItems,
    onFileDrop,
    dropzoneDisabledMessage,
    maximumEnvelopeItemCount,
    onFileDropRejected,
    onDragEnd,
    onEnvelopeItemTitleChange,
    onFileDelete,
    onFailedFileDismiss,
  } = useEnvelopeEditorUpload();

  return (
    <div className="mx-auto w-full min-w-0 max-w-4xl space-y-6 p-4 sm:p-8">
      <input {...getReplaceInputProps()} />

      <EnvelopeEditorInvalidDirectTemplateAlert className="max-w-none" />

      <Card backdropBlur={false} className="border">
        <CardHeader className="p-4 pb-3 sm:p-6 sm:pb-3">
          <CardTitle>
            <Trans>Documents</Trans>
          </CardTitle>
          <CardDescription>
            <Trans>Add and configure multiple documents</Trans>
          </CardDescription>
        </CardHeader>

        <CardContent className="p-4 pt-0 sm:p-6 sm:pt-0">
          {uploadConfig?.allowUpload && (
            <DocumentDropzone
              data-testid="envelope-item-dropzone"
              onDrop={onFileDrop}
              allowMultiple
              className="pt-6 pb-4"
              disabled={dropzoneDisabledMessage !== null}
              disabledMessage={dropzoneDisabledMessage || undefined}
              disabledHeading={msg`Upload disabled`}
              maxFiles={maximumEnvelopeItemCount - localFiles.length}
              onDropRejected={onFileDropRejected}
            />
          )}

          {/* Uploaded Files List */}
          <div className="mt-4">
            <DragDropContext onDragEnd={onDragEnd}>
              <Droppable droppableId="files">
                {(provided) => (
                  <div
                    data-testid="envelope-items-list"
                    {...provided.droppableProps}
                    ref={provided.innerRef}
                    className="space-y-2"
                  >
                    {localFiles.map((localFile, index) => (
                      <Draggable
                        key={localFile.id}
                        isDragDisabled={
                          isCreatingEnvelopeItems ||
                          !envelopeItemPermissions.canOrderBeChanged ||
                          localFile.isReplacing ||
                          !uploadConfig?.allowConfigureOrder
                        }
                        draggableId={localFile.id}
                        index={index}
                      >
                        {(provided, snapshot) => (
                          <div
                            data-testid={`envelope-item-row-${localFile.id}`}
                            ref={provided.innerRef}
                            {...provided.draggableProps}
                            style={provided.draggableProps.style}
                            className={`flex items-center justify-between rounded-lg bg-accent/50 p-3 transition-shadow ${
                              snapshot.isDragging ? 'shadow-md' : ''
                            }`}
                          >
                            <div className="flex min-w-0 items-center space-x-3">
                              {uploadConfig?.allowConfigureOrder && (
                                <div
                                  {...provided.dragHandleProps}
                                  data-testid={`envelope-item-drag-handle-${localFile.id}`}
                                  className="cursor-grab active:cursor-grabbing"
                                >
                                  <GripVerticalIcon className="h-5 w-5 flex-shrink-0 opacity-40" />
                                </div>
                              )}

                              <div className="min-w-0">
                                {localFile.envelopeItemId !== null ? (
                                  <EnvelopeItemTitleInput
                                    disabled={
                                      !envelopeItemPermissions.canTitleBeChanged ||
                                      !uploadConfig?.allowConfigureTitle ||
                                      localFile.isReplacing
                                    }
                                    value={localFile.title}
                                    dataTestId={`envelope-item-title-input-${localFile.id}`}
                                    placeholder={t`Document Title`}
                                    onChange={(title) => {
                                      onEnvelopeItemTitleChange(localFile.envelopeItemId!, title);
                                    }}
                                  />
                                ) : (
                                  <p className="font-medium text-sm">{localFile.title}</p>
                                )}

                                <div className="text-muted-foreground text-xs">
                                  {localFile.isUploading ? (
                                    <Trans>Uploading</Trans>
                                  ) : localFile.isError ? (
                                    <Trans>Something went wrong while uploading this file</Trans>
                                  ) : null}
                                </div>
                              </div>
                            </div>
                            <div className="flex shrink-0 items-center space-x-2">
                              {localFile.isUploading && (
                                <div className="flex h-6 w-10 items-center justify-center">
                                  <Loader2Icon className="h-4 w-4 animate-spin text-muted-foreground" />
                                </div>
                              )}

                              {localFile.isError && (
                                <div className="flex h-6 w-10 items-center justify-center">
                                  <FileWarningIcon className="h-4 w-4 text-destructive" />
                                </div>
                              )}

                              {localFile.isError &&
                                localFile.envelopeItemId === null &&
                                !localFile.isUploading &&
                                !localFile.isReplacing && (
                                  <Button
                                    variant="ghost"
                                    size="sm"
                                    aria-label={t`Remove failed upload`}
                                    data-testid={`envelope-item-dismiss-failed-${localFile.id}`}
                                    onClick={() => onFailedFileDismiss(localFile.id)}
                                  >
                                    <XIcon className="h-4 w-4" />
                                  </Button>
                                )}

                              {localFile.envelopeItemId &&
                                envelopeItemPermissions.canFileBeChanged &&
                                uploadConfig?.allowReplace && (
                                  <Button
                                    variant="ghost"
                                    size="sm"
                                    data-testid={`envelope-item-replace-button-${localFile.id}`}
                                    disabled={localFile.isReplacing || localFile.isUploading}
                                    onClick={() => {
                                      replacingItemIdRef.current = localFile.envelopeItemId;
                                      openReplaceFilePicker();
                                    }}
                                  >
                                    {localFile.isReplacing ? (
                                      <Loader2Icon className="h-4 w-4 animate-spin text-muted-foreground" />
                                    ) : (
                                      <PencilIcon className="h-4 w-4" />
                                    )}
                                  </Button>
                                )}

                              {localFile.envelopeItemId &&
                                uploadConfig?.allowDelete &&
                                (isEmbedded ? (
                                  <Button
                                    variant="ghost"
                                    size="sm"
                                    data-testid={`envelope-item-remove-button-${localFile.id}`}
                                    onClick={() => onFileDelete(localFile.envelopeItemId!)}
                                    disabled={localFile.isReplacing || localFile.isUploading}
                                  >
                                    <XIcon className="h-4 w-4" />
                                  </Button>
                                ) : (
                                  <EnvelopeItemDeleteDialog
                                    canItemBeDeleted={envelopeItemPermissions.canFileBeChanged}
                                    envelopeId={envelope.id}
                                    envelopeItemId={localFile.envelopeItemId}
                                    envelopeItemTitle={localFile.title}
                                    onDelete={onFileDelete}
                                    trigger={
                                      <Button
                                        variant="ghost"
                                        size="sm"
                                        data-testid={`envelope-item-remove-button-${localFile.id}`}
                                        disabled={localFile.isReplacing || localFile.isUploading}
                                      >
                                        <XIcon className="h-4 w-4" />
                                      </Button>
                                    }
                                  />
                                ))}
                            </div>
                          </div>
                        )}
                      </Draggable>
                    ))}
                    {provided.placeholder}
                  </div>
                )}
              </Droppable>
            </DragDropContext>
          </div>
        </CardContent>
      </Card>

      {/* Recipients Section */}
      <EnvelopeEditorRecipientForm />

      {editorConfig.general.allowAddFieldsStep && (
        <div className="flex justify-end">
          <Button type="button" onClick={() => void navigateToStep('addFields')}>
            <Trans>Add Fields</Trans>
          </Button>
        </div>
      )}
    </div>
  );
};
