import { runtime } from "@/runtime"
import { Button, Callout, Container, Flex, TextField } from "@radix-ui/themes"
import { createFileRoute } from "@tanstack/react-router"
import { Array, Effect, Option, Schema } from "effect"
import { Component, Form } from "effect-fc"
import { useContext, useSubscribables } from "effect-fc/hooks"


const email = Schema.pattern<typeof Schema.String>(
    /^(?!\.)(?!.*\.\.)([A-Z0-9_+-.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9-]*\.)+[A-Z]{2,}$/i,

    {
        identifier: "email",
        title: "email",
        message: () => "Not an email address",
    },
)

const RegisterFormSchema = Schema.Struct({
    email: Schema.String.pipe(email),
    password: Schema.String.pipe(Schema.minLength(3)),
})

class RegisterForm extends Effect.Service<RegisterForm>()("RegisterForm", {
    scoped: Form.service({
        schema: RegisterFormSchema,
        initialEncodedValue: { email: "", password: "" },
        submit: () => Effect.void,
    })
}) {}

class RegisterPage extends Component.makeUntraced("RegisterPage")(function*() {
    const form = yield* RegisterForm
    const emailField = Form.useField(form, ["email"])
    const passwordField = Form.useField(form, ["password"])
    const emailInput = yield* Form.useInput(emailField, { debounce: "200 millis" })
    const passwordInput = yield* Form.useInput(passwordField, { debounce: "200 millis" })

    const [canSubmit] = yield* useSubscribables(form.canSubmitSubscribable)

    return (
        <Container>
            <Flex direction="column" gap="2">
                <TextField.Root
                    value={emailInput.value}
                    onChange={e => emailInput.setValue(e.target.value)}
                />

                {Option.match(Array.head(emailInput.issues), {
                    onSome: issue => (
                        <Callout.Root>
                            <Callout.Text>{issue.message}</Callout.Text>
                        </Callout.Root>
                    ),

                    onNone: () => <></>,
                })}

                <TextField.Root
                    value={passwordInput.value}
                    onChange={e => passwordInput.setValue(e.target.value)}
                />

                {Option.match(Array.head(passwordInput.issues), {
                    onSome: issue => (
                        <Callout.Root>
                            <Callout.Text>{issue.message}</Callout.Text>
                        </Callout.Root>
                    ),

                    onNone: () => <></>,
                })}

                <Button disabled={!canSubmit}>Submit</Button>
            </Flex>
        </Container>
    )
}) {}


const RegisterRoute = Component.makeUntraced(function* RegisterRoute() {
    const context = yield* useContext(RegisterForm.Default, { finalizerExecutionMode: "fork" })
    const RegisterRouteFC = yield* Effect.provide(RegisterPage, context)

    return <RegisterRouteFC />
}).pipe(
    Component.withRuntime(runtime.context)
)

export const Route = createFileRoute("/form")({
    component: RegisterRoute
})
