import { FormEvent, useCallback, useEffect, useRef, useState } from "react"
import "../style/settings.css"
import { useAppFetcher, useUser } from "../App.tsx"
import { Fetcher } from "../app/Fetcher.ts"

export default function ProfileSettings() {
    const fetcher = useAppFetcher()
    const [user, setUser] = useUser()

    const [errorMessages, setErrorMessages] = useState<string[]>([])
    const [success, setSuccess] = useState(false)

    const [name, setName] = useState(user!.name)
    const [email, setEmail] = useState(user!.email)
    const [password, setPassword] = useState<string>()
    const [confirmPassword, setConfirmPassword] = useState<string>()

    const passwordConfirmRef = useRef<HTMLInputElement>(null)
    const formRef = useRef<HTMLFormElement>(null)

    const submitForm = useCallback(
        async (e: FormEvent) => {
            e.preventDefault()

            passwordConfirmRef.current!.checkValidity()
            if (password !== confirmPassword) {
                setErrorMessages(["Les mots de passe ne correspondent pas !"])
                return
            }

            const req: AccountUpdateRequest = {
                name: name,
                email: email,
            }
            if (password && password.length !== 0) {
                req.password = password
            }
            const errors = await updateAccount(fetcher, req)
            if (errors.length !== 0) {
                setErrorMessages(errors)
                setSuccess(false)
                return
            }

            setUser({ ...user!, email, name })
            setSuccess(true)
            formRef.current!.reset()
            setErrorMessages([])
        },
        [confirmPassword, email, fetcher, name, password, setUser, user],
    )

    useEffect(() => {
        passwordConfirmRef.current!.setCustomValidity(
            password === confirmPassword
                ? ""
                : "Les mots de passe ne correspondent pas !",
        )
    }, [confirmPassword, password])

    const [modalShow, setModalShow] = useState(false)
    const width = 150

    const profilePicture = user!.profilePicture
    return (
        <div id="settings-page">
            <div id="settings-content">
                {errorMessages.map((msg) => (
                    <div key={msg} className={"error-message"}>
                        {msg}
                    </div>
                ))}
                {success && (
                    <p className={"success-message"}>
                        Modifications sauvegardées
                    </p>
                )}
                <div id="settings-inputs">
                    <div id="settings-profile-picture">
                        <div>
                            <div id="profile-picture">
                                <img
                                    id="profile-picture-img"
                                    src={profilePicture}
                                    width={width}
                                    height={width}
                                    alt="profile-picture"
                                />
                            </div>
                            <button
                                className="settings-button"
                                onClick={() => setModalShow(true)}>
                                Changer photo de profil
                            </button>
                            <ProfileImageInputPopup
                                show={modalShow}
                                onHide={() => setModalShow(false)}
                            />
                        </div>
                    </div>
                    <div>
                        <form
                            ref={formRef}
                            id="credentials-form"
                            onSubmit={submitForm}>
                            <label htmlFor="name">Nom d'utilisateur</label>
                            <input
                                className="settings-input"
                                id="name"
                                name="name"
                                type="text"
                                autoComplete="username"
                                required
                                placeholder="Nom d'utilisateur"
                                value={name}
                                onChange={(e) => setName(e.target.value)}
                            />

                            <label htmlFor="email">Adresse email</label>
                            <input
                                className="settings-input"
                                name="email"
                                id="email"
                                type="email"
                                placeholder={"Adresse email"}
                                autoComplete="email"
                                required
                                value={email}
                                onChange={(e) => setEmail(e.target.value)}
                            />

                            <label htmlFor="password">Mot de passe</label>
                            <input
                                className="settings-input"
                                name="password"
                                id={"password"}
                                type="password"
                                placeholder={"Mot de passe"}
                                autoComplete="new-password"
                                value={password}
                                onChange={(e) => setPassword(e.target.value)}
                            />

                            <label htmlFor="confirmPassword">
                                Confirmez le mot de passe
                            </label>
                            <input
                                ref={passwordConfirmRef}
                                className="settings-input"
                                name="confirmPassword"
                                id="confirmPassword"
                                type="password"
                                autoComplete="new-password"
                                placeholder={"Confirmation du mot de passe"}
                                value={confirmPassword}
                                onChange={(e) =>
                                    setConfirmPassword(e.target.value)
                                }
                            />

                            <button className="settings-button" type="submit">
                                Mettre à jour
                            </button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    )
}

interface AccountUpdateRequest {
    name?: string
    email?: string
    profilePicture?: string
    password?: string
}

async function updateAccount(
    fetcher: Fetcher,
    req: AccountUpdateRequest,
): Promise<string[]> {
    const response = await fetcher.fetchAPI("user", req, "PUT")
    if (response.ok) return []
    const body = await response.json()
    return Object.entries(body).flatMap(([kind, messages]) =>
        (messages as string[]).map((msg) => `${kind}: ${msg}`),
    )
}

interface ProfileImageInputPopupProps {
    show: boolean
    onHide: () => void
}

function ProfileImageInputPopup({ show, onHide }: ProfileImageInputPopupProps) {
    const urlRef = useRef<HTMLInputElement>(null)
    const [errorMessages, setErrorMessages] = useState<string[]>()

    const fetcher = useAppFetcher()
    const [user, setUser] = useUser()

    const [link, setLink] = useState("")

    useEffect(() => {
        function onKeyUp(e: KeyboardEvent) {
            if (e.key === "Escape") onHide()
        }

        window.addEventListener("keyup", onKeyUp)
        return () => window.removeEventListener("keyup", onKeyUp)
    }, [onHide])

    const handleForm = useCallback(
        async (e: FormEvent) => {
            e.preventDefault()

            const url = urlRef.current!.value
            const errors = await updateAccount(fetcher, {
                profilePicture: url,
            })
            if (errors.length !== 0) {
                setErrorMessages(errors)
                return
            }
            setUser({ ...user!, profilePicture: url })
            setErrorMessages([])
            onHide()
        },
        [fetcher, onHide, setUser, user],
    )

    if (!show) return <></>

    return (
        <dialog id="profile-picture-popup">
            <form id="profile-picture-popup-form" onSubmit={handleForm}>
                <div id="profile-picture-popup-header">
                    <p id="profile-picture-popup-title">
                        Nouvelle photo de profil
                    </p>
                </div>

                {errorMessages?.map((msg) => (
                    <div key={msg} className="error-message">
                        {msg}
                    </div>
                ))}
                <label
                    id="profile-picture-popup-subtitle"
                    htmlFor="profile-picture">
                    Saisissez le lien vers votre nouvelle photo de profil
                </label>
                <input
                    className={
                        `settings-input ` +
                        ((errorMessages?.length ?? 0) === 0
                            ? ""
                            : "invalid-input")
                    }
                    id="profile-picture"
                    ref={urlRef}
                    type="url"
                    autoComplete="url"
                    required
                    placeholder={"lien vers une image"}
                    value={link}
                    onChange={(e) => setLink(e.target.value)}
                />
                <div id="profile-picture-popup-footer">
                    <button className={"settings-button"} onClick={onHide}>
                        Annuler
                    </button>
                    <input
                        type="submit"
                        className={"settings-button"}
                        value="Valider"
                    />
                </div>
            </form>
        </dialog>
    )
}
