<script lang="ts">
    import { setContext, type Snippet } from "svelte"
    import { FORM_CONTEXT, type FormContext, type ValidatableField } from "../lib/formContext"
    import type { HTMLFormAttributes } from "svelte/elements"

    let {
        children,
        onsubmit,
        ...rest
    }: {
        children: Snippet
        onsubmit?: (e: SubmitEvent) => void
    } & HTMLFormAttributes = $props()

    const fields: ValidatableField[] = []

    const register = (field: ValidatableField) => {
        fields.push(field)
    }

    const unregister = (field: ValidatableField) => {
        const index = fields.indexOf(field)
        if (index > -1) {
            fields.splice(index, 1)
        }
    }

    setContext<FormContext>(FORM_CONTEXT, {
        register,
        unregister,
    })

    export const validate = async () => {
        let isValid = true
        let firstInvalidField: ValidatableField | null = null

        const results = await Promise.all(
            fields.map(async (field) => {
                const valid = await field.validate()
                return { field, valid }
            })
        )

        for (const { field, valid } of results) {
            if (!valid) {
                isValid = false
                if (!firstInvalidField) {
                    firstInvalidField = field
                }
            }
        }

        if (firstInvalidField && firstInvalidField.focus) {
            firstInvalidField.focus()
        }

        return isValid
    }
</script>

<form novalidate {onsubmit} {...rest}>
    {@render children()}
</form>
