import React, { ReactNode, useState } from "react";
import { Trans, useTranslation } from "react-i18next";
import { graphql, useMutation } from "react-relay";

import { RootLoader } from "../../../layout/Root";
import type {
    AddChildQuery,
    AddChildQuery$data,
} from "./__generated__/AddChildQuery.graphql";
import { loadQuery } from "../../../relay";
import { useRouter } from "../../../router";
import { useForm } from "react-hook-form";
import { Input } from "../../../ui/Input";
import { Form } from "../../../ui/Form";
import { PathSegmentInput } from "../../../ui/PathSegmentInput";
import { PathInvalid } from ".";
import { boxError, NotAuthorized } from "../../../ui/error";
import { displayCommitError, RealmSettingsContainer, realmValidations } from "./util";
import { Button } from "../../../ui/Button";
import { AddChildMutation$data } from "./__generated__/AddChildMutation.graphql";
import { Spinner } from "../../../ui/Spinner";
import { Nav } from "../../../layout/Navigation";
import { makeRoute } from "../../../rauta";
import { Card } from "../../../ui/Card";
import { pathToQuery, ILLEGAL_CHARS, RealmEditLinks, RESERVED_CHARS } from "../../Realm";
import { Breadcrumbs } from "../../../ui/Breadcrumbs";
import { PageTitle } from "../../../layout/header/ui";


export const PATH = "/~manage/realm/add-child";

export const AddChildRoute = makeRoute(url => {
    if (url.pathname !== PATH) {
        return null;
    }

    const parent = url.searchParams.get("parent");
    if (parent === null) {
        return null;
    }

    const queryRef = loadQuery<AddChildQuery>(query, { parent });

    return {
        render: () => <RootLoader
            {...{ query, queryRef }}
            nav={data => data.parent
                ? [
                    <Nav key="main-nav" fragRef={data.parent} />,
                    <RealmEditLinks key="edit-buttons" path={parent} />,
                ]
                : []}
            render={data => {
                const parent = data.parent;
                if (!parent) {
                    return <PathInvalid />;
                } else if (!parent.canCurrentUserEdit) {
                    return <NotAuthorized />;
                } else {
                    return <AddChild parent={parent} />;
                }
            }}
        />,
        dispose: () => queryRef.dispose(),
    };
});


const query = graphql`
    query AddChildQuery($parent: String!) {
        ... UserData
        parent: realmByPath(path: $parent) {
            id
            name
            isRoot
            path
            canCurrentUserEdit
            ancestors { name path }
            children { path }
            ... NavigationData
        }
    }
`;

const addChildMutation = graphql`
    mutation AddChildMutation($realm: NewRealm!) {
        addRealm(realm: $realm) {
            path
            parent { ...NavigationData }
        }
    }
`;

type Props = {
    parent: NonNullable<AddChildQuery$data["parent"]>;
};

const AddChild: React.FC<Props> = ({ parent }) => {
    const { t } = useTranslation();

    type FormData = {
        name: string;
        pathSegment: string;
    };

    const { register, handleSubmit, formState: { errors } } = useForm<FormData>();
    const [commitError, setCommitError] = useState<JSX.Element | null>(null);

    const router = useRouter();

    const [commit, isInFlight] = useMutation(addChildMutation);
    const onSubmit = handleSubmit(data => {
        commit({
            variables: {
                realm: {
                    parent: parent.id,
                    name: data.name,
                    pathSegment: data.pathSegment,
                },
            },
            onCompleted: response => {
                const typedResponse = response as AddChildMutation$data;
                const path = pathToQuery(typedResponse.addRealm.path);
                router.goto(`/~manage/realm/content?path=${path}`);
            },
            onError: error => {
                setCommitError(displayCommitError(error, t("manage.add-child.failed-to-add")));
            },
        });
    });

    const validations = realmValidations(t);
    const breadcrumbs = (parent.isRoot ? parent.ancestors : parent.ancestors.concat(parent))
        .map(({ name, path }) => ({ label: name, link: path }));

    return (
        <RealmSettingsContainer>
            <Breadcrumbs path={breadcrumbs} tail={<i>{t("realm.add-sub-page")}</i>} />
            <PageTitle title={t("manage.add-child.heading")} />
            <p>
                {
                    parent.isRoot
                        ? t("manage.add-child.below-root")
                        : <Trans i18nKey="manage.add-child.below-this-parent">
                            {{ parent: parent.name }}
                        </Trans>
                }
            </p>
            <Form
                onSubmit={onSubmit}
                css={{
                    margin: "32px 0",
                    "& > div": { marginBottom: 32 },
                }}
            >
                <InputWithInfo info={t("manage.add-child.page-name-info")}>
                    <label htmlFor="name-field">{t("manage.realm.general.rename-label")}</label>
                    <Input
                        id="name-field"
                        css={{ width: 350, maxWidth: "100%" }}
                        placeholder={t("manage.realm.general.rename-label")}
                        error={!!errors.name}
                        autoFocus
                        {...register("name", validations.name)}
                    />
                    {boxError(errors.name?.message)}
                </InputWithInfo>

                <InputWithInfo
                    info={<Trans i18nKey="manage.add-child.path-segment-info">
                        {{ illegalChars: ILLEGAL_CHARS, reservedChars: RESERVED_CHARS }}
                    </Trans>}
                >
                    <label htmlFor="path-field">{t("manage.add-child.path-segment")}</label>
                    <PathSegmentInput
                        id="path-field"
                        base={parent.path}
                        error={!!errors.pathSegment}
                        {...register("pathSegment", validations.path)}
                    />
                    {boxError(errors.pathSegment?.message)}
                </InputWithInfo>

                <div>
                    <div css={{ display: "flex", alignItems: "center", gap: 16 }}>
                        <Button type="submit" kind="happy" disabled={isInFlight}>
                            {t("manage.add-child.button-create-page")}
                        </Button>
                        {isInFlight && <Spinner size={20} />}
                    </div>
                    {boxError(commitError)}
                </div>
            </Form>
        </RealmSettingsContainer>
    );
};

type InputWithInfoProps = {
    info: JSX.Element;
    children: ReactNode;
};

const InputWithInfo: React.FC<InputWithInfoProps> = ({ info, children }) => (
    <div css={{
        display: "flex",
        columnGap: 32,
        rowGap: 16,
        "@media (max-width: 1300px)": {
            flexDirection: "column",
        },
        "& code": {
            whiteSpace: "nowrap",
            borderRadius: 4,
            backgroundColor: "var(--grey92)",
            padding: "2px 4px",
        },
    }}>
        <div css={{ minWidth: "min(100%, 450px)" }}>{children}</div>
        <Card kind="info" css={{ maxWidth: 600, minSize: 100, fontSize: 14 }}>{info}</Card>
    </div>
);