import {Dispatch, SetStateAction, useMemo, useState} from 'react';
import styled, {css} from 'styled-components';
import {deleteProduct, replaceProduct} from '../../api/promoApi';
import {useCartPolling} from '../../hooks/useCartPolling';
import {declension} from '../../utils/declension';
import {formatCurrency} from '../../utils/formatCurrency';
import type {Product} from '../../types/cart';
import {CartItem} from './CartItem';
import {CartFooter} from './CartFooter';
import {ProductModal} from './ProductModal';
import {useGlobalZustandState} from "../../hooks/useGlobalZustandState";
import {NotEnoughPopup} from "./NotEnoughPopup";
import {reachGoal} from "../../hooks/useYM";

interface CartProps {
    products: Product[];
    days: number;
    isComplete: boolean;
    isLoading: boolean;
    onProductsChange: Dispatch<SetStateAction<Product[]>>;
    onComplete: () => void;
    onMistake: () => void;
    onLoadingChange: (isLoading: boolean) => void;
}

export function Cart({
                         products,
                         days,
                         isComplete,
                         isLoading,
                         onProductsChange,
                         onComplete,
                         onLoadingChange,
                         onMistake,
                     }: CartProps) {
    const [showNotEnoughPopup, setShowNotEnoughPopup] = useState(false);
    const [visibleCount, setVisibleCount] = useState(5);
    const [showMore, setShowMore] = useState(true);
    const [displayText, setDisplayText] = useState('');
    const [selectedProduct, setSelectedProduct] = useState<Product | null>(null);
    const [processingProductName, setProcessingProductName] = useState<string | null>(null);

    const {showFullRefreshButton, excess} = useGlobalZustandState((state) => state);

    const visibleProducts = showMore ? products.slice(0, visibleCount) : products;
    const remaining = products.length - visibleProducts.length;

    const totalPrice = useMemo(
        () => products.reduce((sum, product) => sum + product.total_price, 0),
        [products],
    );

    const formattedTotalPrice = formatCurrency(totalPrice);
    const stockDays = Math.round(days * excess + days);

    useCartPolling({
        enabled: !isComplete,
        onProductsChange,
        onComplete,
        onLoadingChange,
        setDisplayText,
        onMistake,
    });

    async function handleReplace(product: Product) {
        reachGoal('ac_product_replace_' + product.name);
        setProcessingProductName(product.name);

        try {
            await replaceProduct(product.name);
            onProductsChange(products.filter(item => item.name !== product.name));
        } finally {
            setProcessingProductName(null);
        }
    }

    async function handleDelete(product: Product) {
        reachGoal('ac_product_delete_' + product.name);
        setProcessingProductName(product.name);

        try {
            await deleteProduct(product.name);
            onProductsChange(products.filter(item => item.name !== product.name));
        } finally {
            setProcessingProductName(null);
        }
    }

    return (
        <>
            <Summary>
                <div>
                    <SummaryTitle>
                        Ваша закупка на <Green>{days} {declension(days, ['день', 'дня', 'дней'])}</Green>
                        {showFullRefreshButton && <AbsoluteRefreshButton>Начать заново</AbsoluteRefreshButton>}
                    </SummaryTitle>

                    <SummaryDetails $hidden={isLoading}>
                        {products.length > 0 && (
                            <>
                                <div>
                                    <span>
                                    {products.length} {declension(products.length, ['товар', 'товара', 'товаров'])}
                                </span>
                                    <b>&bull;</b>
                                    <span>{formattedTotalPrice}</span>
                                </div>
                                <SummaryExcess>
                                    с запасами на {stockDays} {declension(stockDays, ['день', 'дня', 'дней'])}
                                </SummaryExcess>
                            </>
                        )}
                    </SummaryDetails>

                    <Loader $hidden={!isLoading} data-display-text={displayText}>
                        {displayText}
                    </Loader>
                </div>
            </Summary>

            <ScrollWrapper>
                <CartList>
                    {visibleProducts.map(product => (
                        <CartItem
                            key={product.name}
                            product={product}
                            isProcessing={processingProductName === product.name}
                            onOpen={() => setSelectedProduct(product)}
                            onReplace={() => handleReplace(product)}
                            onDelete={() => handleDelete(product)}
                        />
                    ))}
                    {products.length > 0 && products.length === visibleProducts.length && isComplete && !isLoading && <NotEnoughWrapper>
                        <ShowNotEnough type="button" onClick={() => {
                            reachGoal('ac_not_enough')
                            setShowNotEnoughPopup(true)
                        }}>
                            Не хватило
                        </ShowNotEnough>
                    </NotEnoughWrapper>}
                </CartList>

                {products.length === 0 && (
                    <EmptyLoader src="/images/empty-cart-loader.svg" alt="сбор корзины"/>
                )}
            </ScrollWrapper>

            {showMore && remaining > 0 && (
                <ShowMoreWrap>
                    <ShowMore type="button" onClick={() => {
                        setShowMore(false);
                    }}>
                        Показать ещё <span>{remaining}</span> товаров
                        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M19 9L12 16L5 9" stroke="#5EA12D" strokeWidth="2" strokeLinecap="round"
                                  strokeLinejoin="round"/>
                        </svg>
                    </ShowMore>
                </ShowMoreWrap>
            )}

            <CartFooter
                isVisible={isComplete}
                totalPrice={formattedTotalPrice}
            />

            <ProductModal
                product={selectedProduct}
                onClose={() => setSelectedProduct(null)}
                onReplace={(product) => {
                    handleReplace(product);
                    setSelectedProduct(null);
                }}
                onDelete={(product) => {
                    handleDelete(product);
                    setSelectedProduct(null);
                }}
            />

            {showNotEnoughPopup && <NotEnoughPopup onClose={() => {
                setShowNotEnoughPopup(false)
            }}/>}
        </>
    );
}

const AbsoluteRefreshButton = styled.button`
    background-color: ${({theme}) => theme.colors.green};
    height: 32px;
    color: #ffffff;
    border: none;
    padding: 14px;
    border-radius: 12px;
    font-size: 16px;
    font-weight: 370;
    line-height: 20px;
    cursor: pointer;
    transition: background 0.2s;
    display: flex;
    align-items: center;
    position: absolute;
    right: 0;
    top: 0;

    &:hover,
    &:focus {
        background-color: ${({theme}) => theme.colors.greenHover};
    }

    &:active {
        background-color: #4A8D19;
    }
`

const Summary = styled.div`
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 24px;
    flex-shrink: 0;
    width: 100%;
    position: relative;
    > div {
        width: 100%;
    }
`;

const SummaryTitle = styled.div`
    font-size: 20px;
    line-height: 24px;
    font-weight: 600;
    color: ${({theme}) => theme.colors.darkGreen};
    margin-bottom: 8px;
    ${({ theme }) => theme.media.mobile(css`
        font-size: 16px;
        line-height: 19px;
    `)}
    ${({ theme }) => theme.media.tablet(css`
        font-size: 16px;
        line-height: 19px;
    `)}
`;

const Green = styled.span`
    color: ${({theme}) => theme.colors.green};
`;

const SummaryDetails = styled.div<{ $hidden: boolean }>`
    min-height: 24px;
    font-size: 14px;
    color: ${({theme}) => theme.colors.gray};
    display: flex;
    flex: 1 1 100%;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    visibility: ${({$hidden}) => ($hidden ? 'hidden' : 'visible')};

    * {
        color:inherit;
    }
    > div:first-child {
        display: flex;
        align-items: center;
        justify-content: start;
        gap: 8px;
    }
    span {
        font-weight: 350;
        white-space: nowrap;
        color:inherit;
    }

    b {
        color:inherit;
        font-family: initial;
        font-size: 20px;
        line-height: 8px;
    }
`;

const SummaryExcess = styled.div`
    background-color: ${({theme}) => theme.colors.paleGreen};
    padding: 3px 6px 5px;
    color: #6D8982;
    border-radius: 4px;
    font-size: 14px;
    font-weight: 350;
    justify-content: center;
`;

const Loader = styled.div<{ $hidden: boolean, "data-display-text": string }>`
    font-size: 16px;
    line-height: 19px;
    display: inline-block;
    color: transparent;
    background-clip: text;
    position: absolute;
    top: 32px;
    visibility: ${({$hidden}) => ($hidden ? 'hidden' : 'visible')};

    &:before,
    &:after {
        content: '${({"data-display-text": displayText}) => displayText}';
        display: block;
        position: absolute;
        inset: 0;
    }

    &:before {
        background: linear-gradient(79deg, #FFBA00 0%, #FFEC47 9%, #C4E30F 24%, #5EA12D 98%) 100%;
        background-clip: text;
        animation: opacityAnim 1s ease-in-out 0s infinite alternate;
    }

    &:after {
        background: linear-gradient(79deg, #5EA12D 2%, #C4E30F 76%, #FFEC47 91%, #FFBA00 100%) 100%;
        background-clip: text;
        animation: opacityAnim 1s ease-in-out -1s infinite alternate;
    }
    ${({ theme }) => theme.media.mobile(css`
        font-size: 14px;
    `)}
    ${({ theme }) => theme.media.tablet(css`
        font-size: 14px;
    `)}
`;

const ScrollWrapper = styled.div`
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding-right: 4px;
    margin-bottom: 0;
    position: relative;
    display: flex;

    &::-webkit-scrollbar {
        width: 6px;
    }

    &::-webkit-scrollbar-track {
        background: #f1f1f1;
        border-radius: 4px;
    }

    &::-webkit-scrollbar-thumb {
        background: #d1d5db;
        border-radius: 4px;
    }
`;

const CartList = styled.ul`
    width: 100%;
    list-style: none;
`;

const EmptyLoader = styled.img`
    animation: spin 1.4s cubic-bezier(0.4, 0.2, 0.35, 0.7) infinite;
    position: absolute;
    left: 50%;
    margin-left: -30px;
    align-self: center;
`;

const ShowMoreWrap = styled.div`
    padding: 16px 8px 24px 8px;
    display: flex;
    justify-content: center;
`;
const ShowMore = styled.button`
    display: flex;
    align-items: center;
    justify-content: center;
    padding:8px 24px;
    border-radius: 8px;
    color: ${({theme}) => theme.colors.green};
    font-size: 14px;
    cursor: pointer;
    font-weight: 500;
    transition: 0.2s;
    flex-shrink: 0;
    gap: 4px;
    border: 0;
    height: 52px;
    background: transparent;

    span {
        color: ${({theme}) => theme.colors.green};
    }

    svg {
        width: 24px;
        height: 24px;
        stroke: ${({theme}) => theme.colors.green};
        stroke-width: 2;
        stroke-linecap: round;
        stroke-linejoin: round;
        margin-left: 6px;
    }

    span {
        color: inherit;
        font-weight: inherit;
    }

    &:hover {
        background-color: #F7FBF6;
    }

    &:active,
    &:focus {
        background-color: #EEF8EB;
        outline: none;
    }
`;

const NotEnoughWrapper = styled.div`
    display: flex;
    flex: 1 1 100%;
    justify-content: center;
`;
const ShowNotEnough = styled(ShowMore)`
    text-align: center;
`;