import React, { useCallback, useState } from 'react';
import { useEffect } from 'react';
import styled from 'styled-components';
import { linkParser } from '@vc3d/providers';
import {
    Button,
    ButtonDropdown,
    DropdownToggle,
    DropdownMenu,
    DropdownItem,
} from 'reactstrap';
import Spinner from 'react-loader-spinner';
import { toast } from 'react-toastify';

import { prefetch, publish } from '../../services/curator';
import { list as listCategories } from '../../services/category';
import ThumbnailSelector from './ThumbnailSelector';
import { useMemo } from 'react';

const Container = styled.div`
    max-width: 1024px;
    margin: 0 auto;
    width: 100%;
`;
const Wrapper = styled(Container)`
    background-color: #ffffff;
    color: #3e4457;
    padding: 20px 60px 120px 60px;
`;
const SearchForm = styled.div`
    align-items: center;
    display: flex;
    flex-direction: row;
    margin: 20px auto;
    padding: 20px 0;
`;
const SubmitForm = styled.div`
    background-color: #ffffff;
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;

    ${Container} {
        padding: 20px 60px;
        align-items: center;
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        margin: 0 auto;
    }

    button {
        padding: 16px;
        font-size: 18px;

        &:active {
            background-color: pink;
            outline: none;
        }
    }

    .dropdown-menu {
        width: 100%;
    }
`;
const Input = styled.input`
    border-radius: 24px;
    border: 3px solid #cccccc;
    box-sizing: content-box;
    flex-grow: 1;
    font-size: 22px;
    height: 30px;
    outline: none;
    padding: 10px 20px;

    &:focus {
        border-color: #3e4457;
    }
`;
const SearchInput = styled(Input)<{ status: string }>`
    margin-left: 20px;

    ${({ status }) => {
        if (status === 'error') {
            return 'border: 3px solid red;';
        }
        if (status === 'success') {
            return 'border: 3px solid green;';
        }
        return 'border: 3px solid #CCCCCC;';
    }}
`;
const Label = styled.label`
    color: #3e4457;
    font-size: 32px;
`;
const Gallery = styled.div`
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-gap: 20px 20px;

    > img {
        max-width: 100%;
    }
`;
const Description = styled.div`
    display: grid;
    grid-gap: 20px 40px;
    grid-template-columns: 1fr 3fr;
    margin: 20px 0;
    text-align: left;

    img {
        align-self: top;
        min-width: 250px;
        max-width: 100%;
    }

    > .details {
        display: flex;
        flex-direction: column;

        .name {
            margin-top: 0;
        }
        .description {
            flex-grow: 1;
        }
        .license {
            margin-bottom: 0;
        }
    }
`;
const TextArea = styled.textarea`
    border-radius: 24px;
    border: 3px solid #cccccc;
    box-sizing: content-box;
    flex-grow: 1;
    font-size: 18px;
    min-height: 350px;
    outline: none;
    padding: 10px 20px;
    margin: 10px 0;

    &:focus {
        border-color: #3e4457;
    }
`;

const canSubmit = (formData: FormData) => {
    if (!formData.get('categoryId')) {
        return false;
    }
    if (!formData.get('link')) {
        return false;
    }
    return true;
};

interface PrefetchData {
    description: string;
    license: string;
    name: string;
    thumbnail: string;
    images: string[];
}

function CuratorScreen() {
    const [link, setLink] = useState('');
    const [isLoading, setLoading] = useState(false);
    const [isSubmitting, setSubmitting] = useState(false);
    const [status, setStatus] = useState('neutral');
    const [categories, setCategories] = useState<Category[]>([]);
    const [data, setData] = useState<PrefetchData | null>(null);
    const [dropdownOpen, setOpen] = useState(false);
    const [category, setCategory] = useState<Category | null>(null);

    const formData = useMemo(() => {
        const formData = new FormData();

        formData.set('categoryId', category?.id ?? '');
        formData.set('description', data?.description ?? '');
        formData.set('images', JSON.stringify(data?.images ?? []));
        formData.set('license', data?.license ?? '');
        formData.set('link', link);
        formData.set('name', data?.name ?? '');
        formData.set('thumbnail', data?.thumbnail ?? '');

        return formData;
    }, [data, category, link]);

    const onChangeLink = useCallback(
        (event) => {
            setLink(event.target.value);
        },
        [setLink]
    );
    const onChangeName = useCallback(
        (event: React.ChangeEvent<HTMLInputElement>) => {
            if (data) {
                setData({
                    ...data,
                    name: event.target.value,
                });
            }
        },
        [data, setData]
    );
    const onChangeDescription = useCallback(
        (event: React.ChangeEvent<HTMLTextAreaElement>) => {
            if (data) {
                setData({
                    ...data,
                    description: event.target.value,
                });
            }
        },
        [data, setData]
    );
    const onChangeThumbnail = useCallback(
        (thumbnail: string) => {
            if (data) {
                setData({
                    ...data,
                    thumbnail,
                });
            }
        },
        [data, setData]
    );
    const onClickPublish = useCallback(async () => {
        setSubmitting(true);

        try {
            await publish(formData);
            setData(null);
            setLink('');
            toast.success('Objeto salvo com sucesso!');
        } catch (error) {
            console.log(error);
            toast.error('Erro ao salvar objeto.');
        } finally {
            setSubmitting(false);
        }
    }, [formData]);

    const doPrefetch = useCallback(async (link: string) => {
        setLoading(true);
        const data = await prefetch(link);
        setLoading(false);
        setData(data);
        console.log(data);
    }, []);
    const doListCategories = useCallback(async () => {
        setLoading(true);
        const categories = await listCategories();
        setLoading(false);
        setCategories(categories);
    }, []);

    useEffect(() => {
        doListCategories();
    }, [doListCategories]);

    useEffect(() => {
        if (linkParser.isValidLink(link)) {
            doPrefetch(link);
            setStatus('success');
        } else if (link) {
            setData(null);
            setStatus('error');
        } else {
            setData(null);
            setStatus('neutral');
        }
    }, [doPrefetch, link]);

    const toggle = () => setOpen(!dropdownOpen);

    return (
        <Wrapper>
            <h1>Curadoria de Objetos - 3d.com.vc</h1>
            <SearchForm>
                <Label>Cole o Link:</Label>
                <SearchInput
                    name="link"
                    onChange={onChangeLink}
                    status={status}
                    value={link}
                />
            </SearchForm>
            {isLoading && <div>Carregando...</div>}
            {!isLoading && data !== null && (
                <div>
                    <Description>
                        <ThumbnailSelector
                            images={data.images}
                            onChange={onChangeThumbnail}
                        />
                        <div className="details">
                            <Input onChange={onChangeName} value={data.name} />
                            <TextArea
                                onChange={onChangeDescription}
                                value={data.description}
                            />
                            <h4 className="license">Licença: {data.license}</h4>
                        </div>
                    </Description>
                    <Gallery>
                        {data.images.map((image) => (
                            <img alt={image} key={image} src={image} />
                        ))}
                    </Gallery>
                    <SubmitForm>
                        <Container>
                            <ButtonDropdown
                                isOpen={dropdownOpen}
                                toggle={toggle}
                            >
                                <DropdownToggle caret>
                                    {category
                                        ? `Categoria: ${category.label}`
                                        : 'Selecione uma Categoria'}
                                </DropdownToggle>
                                <DropdownMenu>
                                    {categories.map((category) => (
                                        <DropdownItem
                                            key={category.id}
                                            onClick={() =>
                                                setCategory(category)
                                            }
                                        >
                                            {category.label}
                                        </DropdownItem>
                                    ))}
                                </DropdownMenu>
                            </ButtonDropdown>
                            <Button
                                disabled={!canSubmit(formData)}
                                color="primary"
                                onClick={onClickPublish}
                            >
                                Importar Objeto
                                {isSubmitting && (
                                    <Spinner
                                        type="TailSpin"
                                        width={14}
                                        height={14}
                                    />
                                )}
                            </Button>
                        </Container>
                    </SubmitForm>
                </div>
            )}
        </Wrapper>
    );
}

export default CuratorScreen;
