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

import HTMLBody from '@composed-components/HTMLBody';
import { type Meta, type StoryObj } from '@storybook/react-vite';

import { type FileCardType } from '../../FileCard/types';

import FormTextArea from './form';
import { prepareForEditor } from './utils/variableSerialization';
import { wrapResizableMedia } from './utils';
import TextArea from '.';

const sampleUploader = (file: File) => {
  return new Promise<FileCardType>(resolve => {
    setTimeout(() => {
      const blobUrl = URL.createObjectURL(file);

      const attachment = {
        url: blobUrl,
        name: file.name,
        type: file.type,
        size: `${(file.size / 1024).toFixed(2)} KB`,
        bytes: file.size,
      };

      resolve({
        status: 'default',
        file,
        attachment,
      });
    }, 200);
  });
};

const defaultSlotProps = {
  insertImage: {
    uploaderProps: {
      uploadFunction: sampleUploader,
    },
  },
  uploadVideo: {
    uploaderProps: {
      uploadFunction: sampleUploader,
    },
  },
};

const meta: Meta<typeof TextArea> = {
  component: TextArea,
  title: 'Design System/TextArea',
  tags: ['autodocs'],
  decorators: [
    Story => {
      const methods = useForm({
        defaultValues: {
          content: '',
        },
      });
      return (
        <FormProvider {...methods}>
          <Story />
        </FormProvider>
      );
    },
  ],
  argTypes: {
    label: {
      description: 'Texto del label',
      control: 'text',
    },
    success: {
      description: 'Indica si el área de texto está en estado de éxito',
      control: 'boolean',
    },
    simplifyEditor: {
      description:
        'Limita la cantidad de opciones disponibles en la barra de herramientas',
      control: 'boolean',
    },
    error: {
      description: 'Indica si el área de texto está en estado de error',
      control: 'boolean',
    },
    errorText: {
      description: 'Texto de error personalizado',
      control: 'text',
    },
    helperText: {
      description: 'Texto de ayuda',
      control: 'text',
    },
    content: {
      description: 'Contenido inicial del área de texto',
      control: 'text',
    },
    placeholder: {
      description: 'Texto de placeholder cuando el área está vacía',
      control: 'text',
    },
    disabled: {
      description: 'Indica si el área de texto está deshabilitada',
      control: 'boolean',
    },
  },
};

export default meta;

type Story = StoryObj<typeof TextArea>;

export const Default: Story = {
  args: {
    content: '',
    placeholder: 'Escribe algo...',
    slotProps: defaultSlotProps,
  },
};

export const SimplifiedEditor: Story = {
  args: {
    content: '',
    placeholder: 'Escribe algo...',
    slotProps: defaultSlotProps,
    simplifyEditor: true,
  },
};

export const WithContent: Story = {
  args: {
    content: `<h1>Este es un contenido inicial con texto <strong>en negrita</strong> y <em>en cursiva</em>.</h1>
      <a href="https://www.google.com" target="_blank" rel="noopener noreferrer">Este es un enlace</a>
      <br />
      <img src="https://picsum.photos/200/300" />
      `,
    placeholder: 'Escribe algo...',
    slotProps: defaultSlotProps,
  },
};

export const WithEvents: Story = {
  args: {
    content: `<h1>Este es un contenido inicial con texto <strong>en negrita</strong> y <em>en cursiva</em>.</h1>
      <a href="https://www.google.com" target="_blank" rel="noopener noreferrer">Este es un enlace</a>
      <br />
      <img src="https://picsum.photos/200/300" />
      `,
    placeholder: 'Escribe algo...',
    slotProps: defaultSlotProps,
    onBlur: () => console.debug('blur'),
    onFocus: () => console.debug('focus'),
  },
};

export const WithExtraActions: Story = {
  args: {
    content: `<h1>Este es un contenido inicial con texto <strong>en negrita</strong> y <em>en cursiva</em>.</h1>
      <a href="https://www.google.com" target="_blank" rel="noopener noreferrer">Este es un enlace</a>
      <br />
      <img src="https://picsum.photos/200/300" />
      `,
    placeholder: 'Escribe algo...',
    slotProps: defaultSlotProps,
    actions: {
      table: true,
      embedHTML: true,
      insertEmoji: true,
    },
  },
};

const sampleVariables = [
  {
    key: 'collaborator',
    label: 'Colaborador',
    children: [
      { key: 'firstName', label: 'Nombre', children: [] },
      { key: 'lastName', label: 'Apellido', children: [] },
      { key: 'hireDate', label: 'Fecha de contratación', children: [] },
    ],
  },
  {
    key: 'manager',
    label: 'Jefe directo',
    children: [
      { key: 'firstName', label: 'Nombre', children: [] },
      { key: 'lastName', label: 'Apellido', children: [] },
      { key: 'email', label: 'Email', children: [] },
    ],
  },
  {
    key: 'buddy',
    label: 'Buddy',
    children: [
      { key: 'firstName', label: 'Nombre', children: [] },
      { key: 'lastName', label: 'Apellido', children: [] },
      { key: 'email', label: 'Email', children: [] },
    ],
  },
];

export const WithVariables: Story = {
  args: {
    content: prepareForEditor(
      '<p>Hola {{collaborator.firstName}}, tu jefe directo es {{manager.firstName}} {{manager.lastName}}.</p>',
      sampleVariables,
    ),
    placeholder: 'Escribe algo...',
    slotProps: {
      ...defaultSlotProps,
      insertVariable: {
        title: 'Agregar variable',
        variables: sampleVariables,
      },
    },
    actions: {
      insertVariable: true,
    },
  },
};

export const DarkMode: Story = {
  globals: {
    themeMode: 'dark',
    backgrounds: { value: 'dark' },
  },
  args: {
    placeholder: 'Escribe algo...',
    slotProps: defaultSlotProps,
    actions: {
      table: true,
      embedHTML: true,
      insertEmoji: true,
    },
    content: `<h1>Dark mode preview</h1>
<p>Texto con <strong>negrita</strong>, <em>cursiva</em> y <a href="https://humand.co" target="_blank" rel="noopener noreferrer">un enlace</a>.</p>
<table>
  <tbody>
    <tr>
      <th><p>Columna A</p></th>
      <th><p>Columna B</p></th>
      <th><p>Columna C</p></th>
    </tr>
    <tr>
      <td><p>Fila 1 - A</p></td>
      <td><p>Fila 1 - B</p></td>
      <td><p>Fila 1 - C</p></td>
    </tr>
    <tr>
      <td><p>Fila 2 - A</p></td>
      <td><p>Fila 2 - B</p></td>
      <td><p>Fila 2 - C</p></td>
    </tr>
  </tbody>
</table>
<blockquote><p>Una cita para validar el blockquote en dark mode.</p></blockquote>
<ul><li><p>Item de lista</p></li><li><p>Otro item</p></li></ul>`,
  },
};

export const CustomToolbar: Story = {
  args: {
    content: '',
    placeholder: 'Placeholder',
    visibleActions: [
      'insertEmoji',
      'bold',
      'italic',
      'underline',
      'strike',
      'insertLink',
      'unorderedList',
      'orderedList',
    ],
  },
};

// Function to prettify html adding \n and \t to each tag
const prettifyHtml = (html: string) => {
  return html?.replaceAll('><', '>\n<');
};

/**
 * Renders HTML produced by a legacy editor (TinyMCE shape: width/height as
 * HTML attributes, `margin:auto` for centering, `float` for alignment) by
 * running it through `wrapResizableMedia` before passing it to the editor.
 *
 * Without the wrapper, sizes default to 100% and `float`/`margin:auto`
 * are ignored. With the wrapper, the legacy markup matches the structure
 * the `resizable-media` extension expects.
 */
export const WithLegacyMigratedContent: Story = {
  args: {
    placeholder: 'Placeholder',
    label: 'Description (legacy migrated)',
    slotProps: defaultSlotProps,
  },
  render: args => {
    const legacyHtml = `
<h1>Legacy onboarding sample</h1>
<p style="text-align:center">
  <img src="https://picsum.photos/seed/center/520/780" alt="" width="260" height="390" style="display:block;margin-left:auto;margin-right:auto">
</p>
<p>
  <video src="https://www.w3schools.com/html/mov_bbb.mp4" controls="controls" width="612" height="306" style="width:612px;height:306px"></video>
</p>
<p>
  <iframe src="https://www.youtube.com/embed/vKQi3bBA1y8" width="342" height="192" style="width:342px;height:192px;float:right" allowfullscreen></iframe>
</p>
<p><br></p>
<p><br></p>
<p><br></p>
<p>Content that the author wanted below the floated iframe.</p>
    `;

    const form = useForm({
      defaultValues: {
        myInput: wrapResizableMedia(legacyHtml),
      },
    });

    const inputValue = form.watch('myInput');

    return (
      <FormProvider {...form}>
        <FormTextArea
          textAreaProps={args}
          name="myInput"
        />
        <details>
          <summary>Migrated HTML (input to the editor)</summary>
          <pre>{prettifyHtml(inputValue)}</pre>
        </details>
      </FormProvider>
    );
  },
};

export const FormTextAreaStory: Story = {
  args: {
    placeholder: 'Placeholder',
    label: 'Label',
    helperText: 'Helper text',
    content: 'value!',
    disabled: false,
    slotProps: defaultSlotProps,
    actions: {
      table: true,
      embedHTML: true,
    },
  },
  render: args => {
    const form = useForm({
      defaultValues: {
        myInput: `
<h1 style="text-align: center">Center aligned</h1>
<a data-type="resizable-media" href="https://github.com/HumandDev/material-hu/tree/SQGZ-861-text-area-fixes" target="_blank" rel="noopener noreferrer nofollow" style="display: block; text-align: center;; max-width: 100%;">
<span style="display: inline-block; width: 33%;">
<img src="https://picsum.photos/200/300">
</span>
</a>
<span data-type="resizable-media" style="display: block; text-align: center;; max-width: 100%;">
<span style="display: inline-block; width: 25%;">
<iframe src="https://www.youtube.com/embed/vKQi3bBA1y8">
</iframe>
</span>
</span>
<span data-type="resizable-media" style="display: block; text-align: right;; max-width: 100%;">
<span style="display: inline-block; width: 50%;">
<video src="https://www.w3schools.com/html/mov_bbb.mp4">
</video>
</span>
</span>
<p>
</p>
      `,
      },
    });

    const onSubmit = () => console.debug('submit');

    const inputValue = form.watch('myInput');

    return (
      <FormProvider {...form}>
        <form onSubmit={form.handleSubmit(onSubmit)}>
          <FormTextArea
            textAreaProps={args}
            rules={{
              required: 'This is a required field',
            }}
            name="myInput"
          />
          <button type="submit">Submit</button>
        </form>
        <details>
          <summary>Parsed HTML</summary>
          <pre>{prettifyHtml(inputValue)}</pre>
        </details>
        <details>
          <summary>HTMLBody rendered</summary>
          <HTMLBody body={inputValue} />
        </details>
      </FormProvider>
    );
  },
};
