import { useTranslation } from "react-i18next";
import { graphql } from "react-relay";

import { RootLoader } from "../layout/Root";
import { SearchQuery, SearchQuery$data } from "./__generated__/SearchQuery.graphql";
import { makeRoute } from "../rauta";
import { loadQuery } from "../relay";
import { Link } from "../router";
import { Thumbnail } from "../ui/Video";
import { unreachable } from "../util/err";
import { Description } from "../ui/metadata";
import { Card } from "../ui/Card";
import { PageTitle } from "../layout/header/ui";
import { FiFolder } from "react-icons/fi";
import { HiOutlineUserCircle } from "react-icons/hi";
import { ReactNode } from "react";


export const isSearchActive = (): boolean => document.location.pathname === "/~search";

export const SearchRoute = makeRoute(url => {
    if (url.pathname !== "/~search") {
        return null;
    }

    const q = url.searchParams.get("q") ?? "";
    const queryRef = loadQuery<SearchQuery>(query, { q });

    return {
        render: () => <RootLoader
            {...{ query, queryRef }}
            nav={() => []}
            render={data => <SearchPage q={q} results={data.search} />}
        />,
        dispose: () => queryRef.dispose(),
    };
});

const query = graphql`
    query SearchQuery($q: String!) {
        ... UserData
        search(query: $q) {
            items {
                id
                __typename
                ... on SearchEvent {
                    title description thumbnail duration creators seriesTitle isLive created
                }
                ... on SearchRealm { name path ancestorNames }
            }
        }
    }
`;

type Props = {
    q: string;
    results: SearchQuery$data["search"];
};

const SearchPage: React.FC<Props> = ({ q, results }) => {
    const { t } = useTranslation();

    return <div css={{ maxWidth: 950, margin: "0 auto" }}>
        <PageTitle title={t("search.title", { query: q })} />
        {results === null
            ? <CenteredNote>{t("search.too-few-characters")}</CenteredNote>
            : results.items.length === 0
                ? <CenteredNote>{t("search.no-results")}</CenteredNote>
                : <SearchResults items={results.items} />
        }
    </div>;
};

const CenteredNote: React.FC<{ children: ReactNode }> = ({ children }) => (
    <div css={{ textAlign: "center" }}>
        <Card kind="info">{children}</Card>
    </div>
);

type SearchResultsProps = {
    items: NonNullable<SearchQuery$data["search"]>["items"];
};

const unwrapUndefined = <T, >(value: T | undefined): T => typeof value === "undefined"
    ? unreachable("type dependent field for search item is not set")
    : value;

const SearchResults: React.FC<SearchResultsProps> = ({ items }) => (
    <ul css={{ listStyle: "none", padding: 0 }}>
        {items.map(item => {
            if (item.__typename === "SearchEvent") {
                return <SearchEvent key={item.id} {...{
                    id: item.id,
                    title: unwrapUndefined(item.title),
                    description: unwrapUndefined(item.description),
                    thumbnail: unwrapUndefined(item.thumbnail),
                    duration: unwrapUndefined(item.duration),
                    creators: unwrapUndefined(item.creators),
                    seriesTitle: unwrapUndefined(item.seriesTitle),
                    isLive: unwrapUndefined(item.isLive),
                    created: unwrapUndefined(item.created),
                }}/>;
            } else if (item.__typename === "SearchRealm") {
                return <SearchRealm key={item.id} {...{
                    id: item.id,
                    name: unwrapUndefined(item.name),
                    fullPath: unwrapUndefined(item.path),
                    ancestorNames: unwrapUndefined(item.ancestorNames),
                }} />;
            } else {
                // eslint-disable-next-line no-console
                console.warn("Unknown search item type: ", item.__typename);
                return null;
            }
        })}
    </ul>
);

type SearchEventProps = {
    id: string;
    title: string;
    description: string | null;
    thumbnail: string | null;
    duration: number;
    creators: readonly string[];
    seriesTitle: string | null;
    isLive: boolean;
    created: string;
};

const SearchEvent: React.FC<SearchEventProps> = ({
    id, title, description, thumbnail, duration, creators, seriesTitle, isLive, created,
}) => {
    const { t } = useTranslation();

    return (
        <Item key={id} link={`/!v/${id.slice(2)}`}>
            <Thumbnail
                event={{
                    ...{ title, isLive, created },
                    thumbnail: thumbnail ?? null,
                    duration: duration,
                    audioOnly: false, // TODO
                }}
                css={{ width: "100%" }}
            />
            <div css={{ color: "black" }}>
                <h3 css={{
                    marginBottom: 6,
                    display: "-webkit-box",
                    WebkitBoxOrient: "vertical",
                    overflow: "hidden",
                    textOverflow: "ellipsis",
                    WebkitLineClamp: 2,
                }}>{title}</h3>
                <div css={{ fontSize: 14, display: "flex", alignItems: "center" }}>
                    <HiOutlineUserCircle css={{
                        color: "var(--grey40)",
                        fontSize: 16,
                        marginRight: 8,
                    }} />
                    {creators.join(", ")}
                </div>
                <Description text={description} lines={3} />
                {/* TODO: link to series */}
                {seriesTitle && <div css={{ fontSize: 14, marginTop: 4 }}>
                    {t("video.part-of-series") + ": " + seriesTitle}
                </div>}
            </div>
        </Item>
    );
};

type SearchRealmProps = {
    id: string;
    name: string;
    ancestorNames: readonly string[];
    fullPath: string;
};

const SearchRealm: React.FC<SearchRealmProps> = ({ id, name, ancestorNames, fullPath }) => (
    <Item key={id} link={fullPath}>
        <div css={{ textAlign: "center" }}>
            <FiFolder css={{ margin: 8, fontSize: 26 }}/>
        </div>
        <div>
            {/* TODO: use proper breadcrumbs, not this uhg */}
            <div>
                {"/ " + ancestorNames.map(name => name + " / ").join("")}
            </div>
            <h3>{name}</h3>
        </div>
    </Item>
);

type ItemProps = {
    link: string;
    children: ReactNode;
};

const Item: React.FC<ItemProps> = ({ link, children }) => (
    <li>
        <Link
            to={link}
            css={{
                display: "flex",
                borderRadius: 4,
                margin: 16,
                padding: 8,
                gap: 16,
                "&:hover": {
                    backgroundColor: "var(--grey97)",
                },
                "& > *:first-child": {
                    minWidth: 200,
                    width: 200,
                },
                "@media(max-width: 480px)": {
                    flexDirection: "column",
                    gap: 12,
                    "& > *:first-child": {
                        width: "100%",
                    },
                },
            }}
        >{children}</Link>
    </li>
);