'use client'

import Image from 'next/image'
import { useEffect, useRef, useState } from 'react'
import { createPortal } from 'react-dom'
import { FiImage, FiUser, FiX } from 'react-icons/fi'
import { hasValidImageSrc } from '@/lib/media/mediaGuards'

const MAX_IMAGE_BYTES = 5 * 1024 * 1024

function readFileAsDataUrl(file: File): Promise<string> {
    return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = () => resolve(String(reader.result ?? ''))
        reader.onerror = () => reject(new Error('read failed'))
        reader.readAsDataURL(file)
    })
}

export default function UserCreateBoardPostModal({
    open,
    onClose,
    title,
    authorName,
    authorAvatar,
    contentPlaceholder,
    addToPostLabel,
    addImageLabel,
    removeImageLabel,
    imageTooLargeLabel,
    imageInvalidLabel,
    submitLabel,
    cancelLabel,
    submitting,
    error,
    onSubmit,
}: {
    open: boolean
    onClose: () => void
    title: string
    authorName: string
    authorAvatar: string | null
    contentPlaceholder: string
    addToPostLabel: string
    addImageLabel: string
    removeImageLabel: string
    imageTooLargeLabel: string
    imageInvalidLabel: string
    submitLabel: string
    cancelLabel: string
    submitting: boolean
    error: string | null
    onSubmit: (content: string, thumbnailUrl: string | null) => Promise<void>
}) {
    const fileInputRef = useRef<HTMLInputElement>(null)
    const textareaRef = useRef<HTMLTextAreaElement>(null)
    const [mounted, setMounted] = useState(false)
    const [content, setContent] = useState('')
    const [imagePreview, setImagePreview] = useState<string | null>(null)
    const [imageDataUrl, setImageDataUrl] = useState<string | null>(null)
    const [localError, setLocalError] = useState<string | null>(null)

    useEffect(() => {
        setMounted(true)
    }, [])

    const resetForm = () => {
        setContent('')
        setImagePreview(null)
        setImageDataUrl(null)
        setLocalError(null)
        if (fileInputRef.current) fileInputRef.current.value = ''
    }

    useEffect(() => {
        if (!open) {
            resetForm()
            return
        }
        const prev = document.body.style.overflow
        document.body.style.overflow = 'hidden'
        const t = window.setTimeout(() => textareaRef.current?.focus(), 80)
        return () => {
            window.clearTimeout(t)
            document.body.style.overflow = prev
        }
    }, [open])

    useEffect(() => {
        if (!open) return
        const onKeyDown = (e: KeyboardEvent) => {
            if (e.key === 'Escape' && !submitting) onClose()
        }
        window.addEventListener('keydown', onKeyDown)
        return () => window.removeEventListener('keydown', onKeyDown)
    }, [open, submitting, onClose])

    const clearImage = () => {
        setImagePreview(null)
        setImageDataUrl(null)
        if (fileInputRef.current) fileInputRef.current.value = ''
    }

    const handleImageChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
        const file = e.target.files?.[0]
        if (!file) return
        setLocalError(null)
        if (!file.type.startsWith('image/')) {
            setLocalError(imageInvalidLabel)
            clearImage()
            return
        }
        if (file.size > MAX_IMAGE_BYTES) {
            setLocalError(imageTooLargeLabel)
            clearImage()
            return
        }
        try {
            const dataUrl = await readFileAsDataUrl(file)
            setImagePreview(dataUrl)
            setImageDataUrl(dataUrl)
        } catch {
            setLocalError(imageInvalidLabel)
            clearImage()
        }
    }

    if (!mounted || !open) return null

    const displayError = localError ?? error
    const canSubmit = Boolean(content.trim() || imageDataUrl)

    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault()
        if (!canSubmit || submitting) return
        await onSubmit(content.trim(), imageDataUrl)
    }

    return createPortal(
        <div
            className="fixed inset-0 z-[320] flex items-center justify-center p-4 sm:p-6"
            role="dialog"
            aria-modal="true"
            aria-label={title}
        >
            <div
                className="absolute inset-0 bg-black/55"
                aria-hidden
                onClick={() => {
                    if (!submitting) onClose()
                }}
            />
            <form
                onSubmit={handleSubmit}
                className="relative z-10 flex w-full max-h-[min(90vh,680px)] max-w-[500px] flex-col overflow-hidden rounded-xl bg-white shadow-[0_12px_28px_rgba(0,0,0,0.2),0_2px_4px_rgba(0,0,0,0.1)] dark:bg-[#242526] dark:shadow-[0_12px_28px_rgba(0,0,0,0.45)]"
            >
                <header className="relative flex shrink-0 items-center justify-center border-b border-gray-200 px-4 py-3 dark:border-[#3e4042]">
                    <h2 className="text-[17px] font-bold leading-tight text-gray-900 dark:text-[#e4e6eb]">
                        {title}
                    </h2>
                    <button
                        type="button"
                        onClick={onClose}
                        disabled={submitting}
                        className="absolute right-2 inline-flex h-9 w-9 items-center justify-center rounded-full bg-gray-200/80 text-gray-700 transition-colors hover:bg-gray-300 disabled:opacity-50 dark:bg-[#3a3b3c] dark:text-[#e4e6eb] dark:hover:bg-[#4e4f50]"
                        aria-label={cancelLabel}
                    >
                        <FiX className="h-5 w-5" strokeWidth={2.5} />
                    </button>
                </header>

                <div className="min-h-0 flex-1 overflow-y-auto">
                    <div className="flex items-start gap-3 px-4 pt-4 pb-2">
                        <div className="relative h-10 w-10 shrink-0 overflow-hidden rounded-full bg-gray-200 dark:bg-[#3a3b3c]">
                            {hasValidImageSrc(authorAvatar) ? (
                                <Image
                                    src={authorAvatar}
                                    alt=""
                                    fill
                                    className="object-cover"
                                    unoptimized
                                />
                            ) : (
                                <span className="flex h-full w-full items-center justify-center text-gray-400 dark:text-[#b0b3b8]">
                                    <FiUser className="h-5 w-5" aria-hidden />
                                </span>
                            )}
                        </div>
                        <div className="min-w-0 flex-1">
                            <p className="text-[15px] font-semibold leading-snug text-gray-900 dark:text-[#e4e6eb]">
                                {authorName}
                            </p>
                            <textarea
                                ref={textareaRef}
                                value={content}
                                onChange={(e) => setContent(e.target.value)}
                                placeholder={contentPlaceholder}
                                rows={4}
                                disabled={submitting}
                                className="mt-1 w-full min-h-[88px] resize-none border-0 bg-transparent p-0 text-[15px] leading-relaxed text-gray-900 placeholder:text-gray-500 focus:outline-none focus:ring-0 disabled:opacity-60 dark:text-[#e4e6eb] dark:placeholder:text-[#b0b3b8]"
                            />
                        </div>
                    </div>

                    {imagePreview ? (
                        <div className="relative mx-4 mb-3 overflow-hidden rounded-lg bg-[#f0f2f5] dark:bg-[#3a3b3c]">
                            {/* eslint-disable-next-line @next/next/no-img-element */}
                            <img
                                src={imagePreview}
                                alt=""
                                className="max-h-[min(50vh,360px)] w-full object-contain"
                            />
                            <button
                                type="button"
                                onClick={clearImage}
                                disabled={submitting}
                                className="absolute right-2 top-2 inline-flex h-9 w-9 items-center justify-center rounded-full bg-white/95 text-gray-800 shadow-md transition-colors hover:bg-white disabled:opacity-50 dark:bg-[#242526]/95 dark:text-[#e4e6eb] dark:hover:bg-[#242526]"
                                aria-label={removeImageLabel}
                            >
                                <FiX className="h-5 w-5" strokeWidth={2} />
                            </button>
                        </div>
                    ) : null}

                    <div className="mx-4 mb-4 overflow-hidden rounded-lg border border-gray-200 dark:border-[#3e4042]">
                        <p className="border-b border-gray-200 px-3 py-2.5 text-[15px] font-semibold text-gray-900 dark:border-[#3e4042] dark:text-[#e4e6eb]">
                            {addToPostLabel}
                        </p>
                        <input
                            ref={fileInputRef}
                            type="file"
                            accept="image/*"
                            className="sr-only"
                            disabled={submitting}
                            onChange={handleImageChange}
                        />
                        <button
                            type="button"
                            disabled={submitting}
                            onClick={() => fileInputRef.current?.click()}
                            className="flex w-full items-center gap-3 px-3 py-2.5 text-left transition-colors hover:bg-gray-50 disabled:opacity-50 dark:hover:bg-[#3a3b3c]/80"
                        >
                            <span className="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-[#e7f3ff] dark:bg-[#263951]">
                                <FiImage
                                    className="h-5 w-5 text-[#1877f2] dark:text-[#2d88ff]"
                                    strokeWidth={2}
                                    aria-hidden
                                />
                            </span>
                            <span className="text-[15px] font-medium text-gray-900 dark:text-[#e4e6eb]">
                                {addImageLabel}
                            </span>
                        </button>
                    </div>

                    {displayError ? (
                        <p className="mx-4 mb-3 text-sm text-red-500 dark:text-red-400" role="alert">
                            {displayError}
                        </p>
                    ) : null}
                </div>

                <footer className="shrink-0 border-t border-gray-200 px-4 py-3 dark:border-[#3e4042]">
                    <button
                        type="submit"
                        disabled={submitting || !canSubmit}
                        className="flex h-10 w-full items-center justify-center rounded-lg text-[15px] font-semibold text-white transition-colors disabled:cursor-not-allowed disabled:bg-[#e4e6eb] disabled:text-[#bcc0c4] enabled:bg-[#1877f2] enabled:hover:bg-[#166fe5] dark:disabled:bg-[#3a3b3c] dark:disabled:text-[#6b6f76] dark:enabled:bg-[#2374e1] dark:enabled:hover:bg-[#2d88ff]"
                    >
                        {submitLabel}
                    </button>
                </footer>
            </form>
        </div>,
        document.body
    )
}
