import { action } from '@storybook/addon-actions';
import { StoryFn, Meta } from '@storybook/react';

import { Status } from '../common';

import UploadInput, { UploadInputProps } from './UploadInput';
import { UploadedFile, UploadResponse } from './types';

const meta: Meta<typeof UploadInput> = {
  title: 'Forms/UploadInput/Tests',
  component: UploadInput,
};

export default meta;
type Story = StoryFn<UploadInputProps>;

const files = [
  {
    id: 1,
    filename: 'purchase-receipt-0.pdf',
    url: 'https://wise.com/public-resources/assets/logos/wise/brand_logo_inverse.svg',
  },
  {
    id: 2,
    filename: 'purchase-receipt-1.pdf',
  },
  {
    id: 3,
    filename: 'purchase-receipt-2.pdf',
    url: 'https://wise.com/public-resources/assets/logos/wise/brand_logo_inverse.svg',
  },
  {
    id: 4,
    filename: 'receipt failed.png',
    status: Status.FAILED,
  },
  {
    id: 5,
    filename: 'receipt failed With error string.png',
    status: Status.FAILED,
    error: 'Something went wrong',
  },
  {
    id: 6,
    filename: 'receipt failed With error object.png',
    status: Status.FAILED,
    error: { message: 'Something went wrong' },
  },
] satisfies UploadedFile[];

const createDelayedPromise = async ({
  successful = true,
  delaySeconds = 3,
  response = { id: Math.round(Math.random() * 10000), url: '#' },
}: {
  successful?: boolean;
  delaySeconds?: number;
  response?: UploadResponse;
} = {}): Promise<UploadResponse> =>
  new Promise((resolve, reject) => {
    setTimeout(
      () => (successful ? resolve(response) : reject(new Error('Unexpected error'))),
      delaySeconds * 1000,
    );
  });

const props = {
  onUploadFile: async (formData: FormData) => {
    return createDelayedPromise();
  },
  onDeleteFile: async (id: string | number) => {
    return createDelayedPromise();
  },
};

const Template: Story = (args: UploadInputProps) => <UploadInput {...args} />;

export const UploadInputWithDescriptionFromProps: Story = Template.bind({});
UploadInputWithDescriptionFromProps.args = {
  ...props,
  multiple: true,
  description: 'Custom file description from prop',
};

export const Disabled: Story = Template.bind({});
Disabled.args = { ...props, disabled: true };

export const WithAnyFileType: Story = Template.bind({});
WithAnyFileType.args = { ...props, fileTypes: '*' };

export const WithSingleFileType: Story = Template.bind({});
WithSingleFileType.args = { ...props, fileTypes: '.zip,application/zip' };

export const WithMultipleExistingFiles: Story = Template.bind({});
WithMultipleExistingFiles.args = {
  ...props,
  files,
  multiple: true,
};

export const WithFileErrors: Story = Template.bind({});
WithFileErrors.args = {
  ...props,
  files: [
    {
      id: 1,
      filename: 'Error with default message.png',
      status: Status.FAILED,
    },
    {
      id: 2,
      filename: 'Error with `string` error.png',
      status: Status.FAILED,
      error: 'Single string error',
    },
    {
      id: 3,
      filename: 'Error with `obj` error ({ message : `string` }).png',
      status: Status.FAILED,
      error: { message: 'Single obj error' },
    },
    {
      id: 4,
      filename: 'Error with single error passed in `array`.png',
      status: Status.FAILED,
      errors: ['Single error in array'],
    },
    {
      id: 5,
      filename: 'Error with multiple `string` errors passed in `array`.png',
      status: Status.FAILED,
      errors: [
        'Error 1',
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
        'Error 3',
      ],
    },
    {
      id: 6,
      filename: 'Error with multiple `obj` errors passed in `array`.png',
      status: Status.FAILED,
      errors: [
        { message: 'Error 1' },
        {
          message:
            'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
        },
        { message: 'Error 3' },
      ],
    },
  ],
  multiple: true,
};

export const WithoutDelete: Story = Template.bind({});
WithoutDelete.args = {
  ...props,
  files,
  onDeleteFile: undefined,
  multiple: true,
};

export const WithUploadFailed: Story = Template.bind({});
WithUploadFailed.args = {
  ...props,
  files: files.slice(0),
  onUploadFile: async () => createDelayedPromise({ successful: false }),
  multiple: true,
};

export const WithDeleteFailed: Story = Template.bind({});
WithDeleteFailed.args = {
  ...props,
  files: files.slice(0),
  onDeleteFile: async () => createDelayedPromise({ successful: false }),
  multiple: true,
};

export const CustomConfirmMessage: Story = Template.bind({});
CustomConfirmMessage.args = {
  ...props,
  files: files.slice(0),
  deleteConfirm: {
    title: 'Sure you want to remove this invoice?',
    body: (
      <img
        alt="brand logo"
        src="https://wise.com/public-resources/assets/logos/wise/brand_logo.svg"
      />
    ),
  },
};

export const WithManualDownloadHandler: Story = Template.bind({});
WithManualDownloadHandler.args = {
  ...props,
  files,
  onDownload: action('Manual download handler'),
};

export const WithFilesChangeHandler: Story = Template.bind({});
WithFilesChangeHandler.args = {
  ...props,
  files,
  onFilesChange: action('Files change handler'),
};

export const WithMaxFilesToUploadLimit: Story = Template.bind({});
WithMaxFilesToUploadLimit.args = {
  ...props,
  multiple: true,
  maxFiles: 5,
  maxFilesErrorMessage: "Can't upload as maximum number of files allowed are already uploaded",
};

export const WithFileSizeErrorMessage: Story = Template.bind({});
WithFileSizeErrorMessage.args = {
  ...props,
  sizeLimit: 1,
  sizeLimitErrorMessage: 'The file is oversized',
};

export const WithCustomUploadButtonTitle: Story = Template.bind({});
WithCustomUploadButtonTitle.args = {
  ...props,
  uploadButtonTitle: 'Upload the VAT receipts for FY 2022-23',
};
