import * as React from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import { cn } from '@/lib/utils';

/**
 * Single-slide testimonial carousel: company logo on top, the review
 * quote, client name/role, and their avatar below, with dot pagination
 * and swipe/drag support. Ported from a Next.js/shadcn `TestimonialCarousel`
 * + embla `Carousel` pair the user supplied, adapted to this project:
 *   - `next/image` -> plain `<img>` (no Next.js here)
 *   - shadcn's embla-based `@/components/ui/carousel` -> framer-motion,
 *     which is already a dependency, so no new package is needed
 *   - shadcn tokens (`foreground`, `primary`, `muted-foreground`) ->
 *     this project's own design tokens (`heading`, `paragraph`, `primary`)
 *   - `testimonial.avatar` / `testimonial.company` + a logo-path
 *     convention -> the real fields the backend sends per testimonial
 *     (`photoUrl`, `companyLogoUrl`, `clientName`, ...)
 *
 * @param {object} props
 * @param {{id:number,clientName:string,photoUrl:string|null,company:string|null,companyLogoUrl:string|null,country:string|null,review:string,rating:number}[]} props.testimonials
 * @param {string} [props.className]
 * @param {number} [props.autoplayMs=6000] - set to 0 to disable autoplay.
 */
export function TestimonialCarousel({ testimonials, className, autoplayMs = 6000 }) {
    const [index, setIndex] = React.useState(0);
    const [direction, setDirection] = React.useState(1);

    const count = testimonials?.length ?? 0;

    const goTo = React.useCallback(
        (nextIndex, dir = 1) => {
            if (count === 0) return;
            setDirection(dir);
            setIndex(((nextIndex % count) + count) % count);
        },
        [count],
    );

    React.useEffect(() => {
        if (!autoplayMs || count < 2) return undefined;
        const timer = setInterval(() => goTo(index + 1, 1), autoplayMs);
        return () => clearInterval(timer);
    }, [index, count, autoplayMs, goTo]);

    if (!count) return null;

    const current = testimonials[index];
    // Reserve the tall slide area only when some testimonial actually has a logo/photo;
    // text-only slides (quote + name) need far less room, otherwise the quote floats in empty space.
    const hasMedia = testimonials.some((item) => item.companyLogoUrl || item.photoUrl);
    const roleLine = [current.company, current.country].filter(Boolean).join(' · ');

    return (
        <div className={cn(className)}>
            <div className="relative mx-auto max-w-screen-xl px-4 lg:px-14">
                {count > 1 && (
                    <>
                        <button
                            type="button"
                            onClick={() => goTo(index - 1, -1)}
                            className="absolute left-0 top-1/2 z-10 flex size-9 -translate-y-1/2 cursor-pointer appearance-none items-center justify-center rounded-full border border-border bg-background p-0 text-paragraph transition-colors hover:bg-soft-background sm:size-10"
                            aria-label="Previous testimonial"
                        >
                            <ChevronLeft className="size-4 sm:size-5" />
                        </button>
                        <button
                            type="button"
                            onClick={() => goTo(index + 1, 1)}
                            className="absolute right-0 top-1/2 z-10 flex size-9 -translate-y-1/2 cursor-pointer appearance-none items-center justify-center rounded-full border border-border bg-background p-0 text-paragraph transition-colors hover:bg-soft-background sm:size-10"
                            aria-label="Next testimonial"
                        >
                            <ChevronRight className="size-4 sm:size-5" />
                        </button>
                    </>
                )}

                {/* Fixed-height slide area: a 1-line quote and a 4-line quote
                    both center inside the same box, so the pagination dots
                    below never jump up/down as testimonials change. */}
                <div
                    className={cn(
                        'mx-auto flex max-w-xl flex-col items-center justify-center overflow-hidden',
                        hasMedia ? 'min-h-[19rem] sm:min-h-[17rem]' : 'min-h-[11rem]',
                    )}
                >
                    <AnimatePresence mode="wait" initial={false} custom={direction}>
                        <motion.div
                            key={current.id}
                            custom={direction}
                            initial={{ opacity: 0, x: 60 * direction }}
                            animate={{ opacity: 1, x: 0 }}
                            exit={{ opacity: 0, x: -60 * direction }}
                            transition={{ duration: 0.35, ease: 'easeOut' }}
                            drag="x"
                            dragConstraints={{ left: 0, right: 0 }}
                            dragElastic={0.2}
                            onDragEnd={(_, info) => {
                                if (info.offset.x < -60) goTo(index + 1, 1);
                                else if (info.offset.x > 60) goTo(index - 1, -1);
                            }}
                            className="flex w-full cursor-grab flex-col items-center active:cursor-grabbing"
                        >
                            {current.companyLogoUrl && (
                                <div className="mb-6 flex h-7 items-center">
                                    <img
                                        src={current.companyLogoUrl}
                                        alt={current.company ? `${current.company} logo` : ''}
                                        className="h-7 max-w-28 object-contain"
                                        draggable={false} loading="lazy" decoding="async" />
                                </div>
                            )}

                            <p className="line-clamp-4 text-balance text-center text-base text-heading sm:text-lg">
                                {current.review}
                            </p>

                            <h5 className="mt-5 text-sm font-medium text-paragraph">{current.clientName}</h5>

                            {roleLine && <h5 className="mt-1 text-sm font-medium text-paragraph/50">{roleLine}</h5>}

                            {current.photoUrl && (
                                <div className="mt-5 size-11 overflow-hidden rounded-full bg-soft-background">
                                    <img
                                        src={current.photoUrl}
                                        alt={current.clientName}
                                        className="size-full object-cover"
                                        draggable={false} loading="lazy" decoding="async" />
                                </div>
                            )}
                        </motion.div>
                    </AnimatePresence>
                </div>

                {count > 1 && (
                    <div className="mt-1 flex items-center justify-center gap-1">
                        {testimonials.map((testimonial, dotIndex) => (
                            <button
                                key={testimonial.id}
                                type="button"
                                onClick={() => goTo(dotIndex, dotIndex > index ? 1 : -1)}
                                className="flex cursor-pointer appearance-none items-center justify-center border-0 bg-transparent p-1.5"
                                aria-label={`Go to testimonial ${dotIndex + 1}`}
                            >
                                <span
                                    className={cn(
                                        'block size-1.5 rounded-full transition-colors',
                                        dotIndex === index ? 'bg-primary' : 'bg-primary/30',
                                    )}
                                />
                            </button>
                        ))}
                    </div>
                )}
            </div>
        </div>
    );
}
