import { useState } from 'react'
import FancyTextEditor, { TextInputKeyDownEvent } from './inputs/FancyTextEditor.tsx'
import Button from './buttons/Button.tsx'
import { openFileDialog } from '../utils/openFileDialog.ts'

interface NewPostWidgetProps {
  onSubmit: (
    content: string,
    media: { file: File; width: number; height: number }[],
    isPublic: boolean,
  ) => void
  isSubmitting?: boolean
}

interface Attachment {
  id: string
  file: File
  objectUrl: string
  width: number
  height: number
}

export default function NewPostWidget({ onSubmit, isSubmitting = false }: NewPostWidgetProps) {
  const [content, setContent] = useState('')
  const [attachments, setAttachments] = useState<Attachment[]>([])
  const [isPublic, setIsPublic] = useState(false)

  const onContentInput = (value: string) => {
    setContent(value)
  }

  async function onAddMediaClicked() {
    const files = await openFileDialog('image/*', true)
    if (files == null || files.length === 0) {
      return
    }

    const newAttachments = await Promise.all(Array.from(files).map(createAttachment))
    setAttachments((attachments) => [...attachments, ...newAttachments])
  }

  const handleSubmit = () => {
    if (!content.trim() && attachments.length === 0) {
      return
    }

    onSubmit(content, attachments, isPublic)

    attachments.forEach(({ objectUrl }) => URL.revokeObjectURL(objectUrl))
    setContent('')
    setAttachments([])
  }

  const handleRemoveMedia = (id: string) => {
    const attachment = attachments.find((attachment) => attachment.id === id)!
    setAttachments(attachments.filter((attachment) => attachment.id !== id))
    URL.revokeObjectURL(attachment.objectUrl)
  }

  const onInputKeyDown = (e: TextInputKeyDownEvent) => {
    if (e.key === 'Enter' && e.ctrlKey) {
      e.preventDefault()
      handleSubmit()
    }
  }

  return (
    <div className="w-full p-4 border-b border-gray-200">
      <FancyTextEditor
        value={content}
        onInput={onContentInput}
        onKeyDown={onInputKeyDown}
        className="mb-3"
        placeholder="write something..."
      />

      {attachments.length > 0 && (
        <div className="flex flex-row flex-wrap gap-2 mb-3">
          {attachments.map(({ objectUrl, id }) => (
            <button
              key={id}
              className="relative cursor-pointer"
              onClick={() => handleRemoveMedia(id)}
              disabled={isSubmitting}
            >
              <img src={objectUrl} alt="" className="w-24 h-24 object-cover rounded-md" />
            </button>
          ))}
        </div>
      )}

      <div className="flex justify-between items-center pt-2">
        <div className="flex items-center gap-2">
          <Button secondary onClick={onAddMediaClicked}>
            + add media
          </Button>
          <label className="flex items-center gap-1 cursor-pointer">
            <input
              type="checkbox"
              checked={isPublic}
              onChange={(e) => setIsPublic(e.target.checked)}
              disabled={isSubmitting}
              className="form-checkbox h-4 w-4 text-blue-600"
            />
            <span className="text-primary-500">public</span>
          </label>
        </div>
        <Button
          onClick={handleSubmit}
          disabled={isSubmitting || (content.trim() === '' && attachments.length === 0)}
        >
          post
        </Button>
      </div>
    </div>
  )
}

async function createAttachment(file: File): Promise<Attachment> {
  if (!file.type.startsWith('image/')) {
    throw new Error('not an image')
  }

  const objectUrl = URL.createObjectURL(file)
  const { width, height } = await getImageFileDimensions(objectUrl)

  return {
    id: crypto.randomUUID(),
    file,
    objectUrl,
    width,
    height,
  }
}

function getImageFileDimensions(objectURL: string): Promise<{ width: number; height: number }> {
  return new Promise((resolve) => {
    const img = document.createElement('img')

    img.addEventListener('load', () => {
      resolve({ width: img.width, height: img.height })
    })

    img.src = objectURL
  })
}
