/* eslint-disable no-console */

import { FormProvider, useForm } from 'react-hook-form';

import { IconButton, Link, Stack, Typography } from '@mui/material';
import { type Meta, type StoryObj } from '@storybook/react-vite';
import { IconFileUpload } from '@tabler/icons-react';

import { useModal } from '../../../hooks/useModal';
import Chip from '../Chip';
import Dialog from '../Dialog';
import { mockFile } from '../FileCard/stories';

import { typeMap } from './constants';
import FormUploader from './form';
import Uploader from '.';

const meta: Meta<typeof Uploader> = {
  component: Uploader,
  title: 'Design System/Uploader/Uploader',
  tags: ['autodocs'],
  argTypes: {
    label: { control: 'text' },
    helperText: { control: 'text' },
    title: { control: 'text' },
    description: { control: 'text' },
    error: { control: 'boolean' },
    disabled: { control: 'boolean' },
    readOnly: { control: 'boolean' },
    maxFiles: { control: 'number' },
    fileSizeLimit: { control: 'number' },
    triggerOnChangeWhenUploading: { control: 'boolean' },
    showUploadButtonOnMaxFiles: { control: 'boolean' },
    acceptedTypes: { control: false },
    value: { control: false },
    onChange: { control: false },
    uploadFunction: { control: false },
    onDropAccepted: { control: false },
    onDropRejected: { control: false },
    onFilesUploaded: { control: false },
    fileCardProps: { control: false },
    slotProps: { control: false },
    sx: { control: false },
  },
  args: {
    helperText: 'Helper Text',
    label: 'Label',
    value: [],
    onDropAccepted: files => {
      console.log('onDropAccepted', files);
    },
    onDropRejected: (files, event) => {
      console.log('onDropRejected', files, event);
    },
    sx: { width: '100%' },
  },
};

export default meta;

type Story = StoryObj<typeof Uploader>;

export const WithUploads: Story = {
  args: {
    value: [
      {
        status: 'success',
        file: mockFile,
      },
      {
        status: 'error',
        file: mockFile,
      },
      {
        status: 'uploading',
        file: mockFile,
      },
      {
        status: 'default',
        attachment: {
          url: 'https://picsum.photos/200',
          name: 'test.png',
          type: 'image/png',
          size: '100KB',
          bytes: 100,
        },
      },
    ],
  },
};

export const UploaderWithForm: Story = {
  render: () => {
    const form = useForm({
      defaultValues: {
        files: [],
      },
    });
    return (
      <FormProvider {...form}>
        <FormUploader
          name="files"
          uploaderProps={{
            sx: { width: '100%' },
            label: 'Upload Files',
            helperText: 'Upload your files here',
            acceptedTypes: ['image', 'video', 'msword', 'pdf'],
            uploadFunction: file =>
              new Promise(resolve =>
                resolve({
                  status: 'success',
                  file,
                }),
              ),
          }}
        />
      </FormProvider>
    );
  },
};

export const UploaderFormWithMaxFiles: Story = {
  render: () => {
    const form = useForm({
      defaultValues: {
        documents: [],
      },
    });
    return (
      <FormProvider {...form}>
        <FormUploader
          name="documents"
          fileCardProps={{
            onRemove: fileCard => {
              alert(`onRemove intercepted ${fileCard.file?.name}`);
            },
          }}
          uploaderProps={{
            sx: { width: '100%' },
            label: 'Upload Files',
            helperText: 'Upload your files here',
            maxFiles: 2,
            acceptedTypes: ['pdf'],
            uploadFunction: file =>
              new Promise(resolve =>
                resolve({
                  status: 'success',
                  file,
                }),
              ),
          }}
        />
      </FormProvider>
    );
  },
};

export const UploaderFormWithOneFileAllowed: Story = {
  render: () => {
    const form = useForm({
      defaultValues: {
        files: [],
      },
    });

    return (
      <FormProvider {...form}>
        <FormUploader
          name="files"
          uploaderProps={{
            sx: { width: '100%' },
            label: 'Upload Files',
            helperText: 'Upload your files here',
            maxFiles: 1,
            uploadFunction: file =>
              new Promise(resolve =>
                resolve({
                  status: 'success',
                  file,
                }),
              ),
            onDropAccepted: () => {
              alert('onDropAccepted intercepted');
              form.setValue('files', []);
            },
          }}
          fileCardProps={{
            disabled: true,
          }}
        />
      </FormProvider>
    );
  },
};

export const UploaderFormDisabled: Story = {
  render: () => {
    const form = useForm({
      defaultValues: {
        files: [],
      },
    });

    return (
      <FormProvider {...form}>
        <FormUploader
          name="files"
          uploaderProps={{
            sx: { width: '100%' },
            label: 'Upload Files',
            helperText: 'Upload your files here',
            disabled: true,
            acceptedTypes: ['pdf'],
            uploadFunction: file =>
              new Promise(resolve =>
                resolve({
                  status: 'success',
                  file,
                }),
              ),
            onDropAccepted: () => {
              alert('onDropAccepted intercepted');
              form.setValue('files', []);
            },
          }}
          fileCardProps={{
            disabled: true,
          }}
        />
      </FormProvider>
    );
  },
};

export const UploaderFormWithFileCardDisabled: Story = {
  render: () => {
    const form = useForm({
      defaultValues: {
        files: [],
      },
    });

    return (
      <FormProvider {...form}>
        <FormUploader
          name="files"
          uploaderProps={{
            sx: { width: '100%' },
            label: 'Upload Files',
            helperText: 'Upload your files here',
            maxFiles: 1,
            uploadFunction: file =>
              new Promise(resolve =>
                resolve({
                  status: 'success',
                  file,
                }),
              ),
          }}
          fileCardProps={{
            disabled: true,
          }}
        />
      </FormProvider>
    );
  },
};

export const UploaderFormWithJustPdfAllowed: Story = {
  render: () => {
    const form = useForm({
      defaultValues: {
        files: [],
      },
    });

    return (
      <FormProvider {...form}>
        <FormUploader
          name="files"
          uploaderProps={{
            sx: { width: '100%' },
            label: 'Upload Files',
            helperText: 'Upload your files here',
            maxFiles: 1,
            acceptedTypes: ['pdf'],
            uploadFunction: file =>
              new Promise(resolve =>
                resolve({
                  status: 'success',
                  file,
                }),
              ),
          }}
        />
      </FormProvider>
    );
  },
};

const formatGroups: { label: string; extensions: string[] }[] = Object.entries(
  typeMap,
).map(([key, { extensions }]) => ({
  label: key.charAt(0).toUpperCase() + key.slice(1),
  extensions,
}));

const AllowedFormatsDialogContent = ({ onClose }: { onClose: () => void }) => (
  <Dialog
    title="Allowed formats"
    onClose={onClose}
    body={
      <Stack sx={{ gap: 2 }}>
        {formatGroups.map(({ label, extensions }) => (
          <Stack
            key={label}
            sx={{ gap: 1 }}
          >
            <Typography
              variant="globalXS"
              fontWeight="fontWeightSemiBold"
            >
              {label}
            </Typography>
            <Stack sx={{ flexDirection: 'row', flexWrap: 'wrap', gap: 0.5 }}>
              {extensions.map(ext => (
                <Chip
                  key={ext}
                  label={ext}
                  size="small"
                />
              ))}
            </Stack>
          </Stack>
        ))}
      </Stack>
    }
  />
);

export const WithCustomDropzoneBody: Story = {
  render: () => {
    const { modal, showModal } = useModal(AllowedFormatsDialogContent, {
      maxWidth: 'xs',
      fullWidth: true,
    });

    return (
      <>
        {modal}
        <Uploader
          sx={{ width: '100%' }}
          label="Upload Files"
          helperText="Upload your files here"
          value={[]}
          onChange={files => console.log('onChange', files)}
          uploadFunction={file =>
            new Promise(resolve => resolve({ status: 'success', file }))
          }
        >
          <Stack sx={{ gap: 0.5, alignItems: 'center' }}>
            <IconButton variant="secondary">
              <IconFileUpload color="primary" />
            </IconButton>
            <Typography
              variant="globalS"
              fontWeight="fontWeightSemiBold"
            >
              Upload a file or drag and drop
            </Typography>
            <Typography
              variant="globalXS"
              sx={{ color: theme => theme.palette.new.text.neutral.lighter }}
            >
              You can upload files in the{' '}
              <Link
                component="button"
                type="button"
                variant="globalXS"
                onClick={e => {
                  e.stopPropagation();
                  showModal();
                }}
              >
                allowed formats
              </Link>{' '}
              up to 100 MB.
            </Typography>
          </Stack>
        </Uploader>
      </>
    );
  },
};
