"use client";

import { AnimatePresence, motion } from "framer-motion";
import Image from "next/image";
import { useEffect, useMemo, useRef, useState } from "react";
import {
    getMediaUrl,
    getPortfolioCards,
    getPortfolioModalSettings,
} from "../../../lib/strapiClient";
import { gaEvent } from "../../../lib/ga";

/* =======================
   KONFIG: Strapi base URL
   ======================= */
const STRAPI_BASE = "https://admin.laskar.pl";

// Animacje
const fadeInUp = {
    initial: { opacity: 0, y: 40 },
    animate: { opacity: 1, y: 0 },
};

/* =======================
   Helpers: URL + image/video
   ======================= */
function toAbsoluteStrapiUrl(url: string | null): string | null {
    if (!url) return null;
    const trimmed = url.trim();
    if (!trimmed) return null;
    if (/^https?:\/\//i.test(trimmed)) return trimmed;
    if (trimmed.startsWith("/")) return `${STRAPI_BASE}${trimmed}`;
    return `${STRAPI_BASE}/${trimmed}`;
}

function isVideoUrl(url: string): boolean {
    const clean = String(url).split("?")[0].split("#")[0].toLowerCase();
    return (
        clean.endsWith(".mp4") ||
        clean.endsWith(".webm") ||
        clean.endsWith(".ogg") ||
        clean.endsWith(".mov") ||
        clean.endsWith(".m4v") ||
        clean.endsWith(".m3u8")
    );
}

/**
 * Obsługuje:
 * - string: "/uploads/a.jpg"
 * - obiekt z url: { url: "/uploads/a.jpg" }
 * - Strapi single: { data: { attributes: { url } } }
 * - Strapi multiple: { data: [{ attributes: { url } }] } (bierze pierwsze)
 * - fallback: getMediaUrl(input)
 */
function safeMediaUrl(input: unknown): string | null {
    if (!input) return null;

    if (typeof input === "string") return toAbsoluteStrapiUrl(input);

    const anyInput = input as any;
    if (typeof anyInput?.url === "string") return toAbsoluteStrapiUrl(anyInput.url);

    const single = anyInput?.data?.attributes?.url;
    if (typeof single === "string") return toAbsoluteStrapiUrl(single);

    const first = anyInput?.data?.[0]?.attributes?.url;
    if (typeof first === "string") return toAbsoluteStrapiUrl(first);

    const raw = String(getMediaUrl(anyInput) || "").trim();
    return toAbsoluteStrapiUrl(raw);
}

/* =======================
   Strapi Blocks renderer
   ======================= */
type InlineNode = {
    type?: string;
    text?: string;
    bold?: boolean;
    italic?: boolean;
    underline?: boolean;
    code?: boolean;
    url?: string;
    children?: InlineNode[];
};

type Block =
    | { type: "paragraph"; children: InlineNode[] }
    | { type: "heading"; level?: number; children: InlineNode[] }
    | {
    type: "bulleted-list" | "numbered-list";
    children: { type: "list-item"; children: InlineNode[] }[];
}
    | { type: "list-item"; children: InlineNode[] }
    | { type: string; children?: InlineNode[]; [k: string]: any };

function normalizeToBlocks(input: unknown): Block[] {
    if (Array.isArray(input)) return input as Block[];
    if (typeof input === "string") {
        return [
            {
                type: "paragraph",
                children: [{ type: "text", text: input }],
            } as Block,
        ];
    }
    return [];
}

function pullPlain(nodes: InlineNode[] = []): string {
    return nodes
        .map((n) => (n.text ? n.text : n.children ? pullPlain(n.children) : ""))
        .join("");
}

function blocksToPlainText(blocks: Block[] = []): string {
    const parts: string[] = [];
    for (const b of blocks) {
        if (!b) continue;
        if (b.type === "paragraph" || b.type === "heading" || b.type === "list-item") {
            parts.push(pullPlain((b as any).children || []));
        } else if (b.type === "bulleted-list" || b.type === "numbered-list") {
            for (const li of (b as any).children || []) {
                parts.push(pullPlain(li.children || []));
            }
        }
    }
    return parts
        .join("\n")
        .replace(/\s+\n/g, "\n")
        .replace(/\n{3,}/g, "\n\n")
        .trim();
}

function preview30(text: string): string {
    if (!text) return "";
    if (text.length <= 30) return text;
    return text.slice(0, 30).trimEnd() + "[...]";
}

function Inline({
                    nodes = [] as InlineNode[],
                    onLinkClick,
                }: {
    nodes?: InlineNode[];
    onLinkClick?: (href: string) => void;
}) {
    return (
        <>
            {nodes.map((n, i) => {
                if (n.type === "link") {
                    const href = n.url || "#";
                    return (
                        <a
                            key={i}
                            href={href}
                            target="_blank"
                            rel="noopener noreferrer"
                            className="underline underline-offset-2 hover:opacity-90"
                            onClick={(e) => {
                                e.stopPropagation();
                                onLinkClick?.(href);
                            }}
                        >
                            <Inline nodes={n.children || []} onLinkClick={onLinkClick} />
                        </a>
                    );
                }

                const content = n.text ?? null;

                let el: React.ReactNode = content;
                if (n.children?.length) el = <Inline nodes={n.children} onLinkClick={onLinkClick} />;

                if (n.code) el = <code className="px-1 py-0.5 rounded bg-white/10 font-mono">{el}</code>;
                if (n.bold) el = <span className="font-semibold">{el}</span>;
                if (n.italic) el = <span className="italic">{el}</span>;
                if (n.underline) el = <span className="underline">{el}</span>;

                return <span key={i}>{el}</span>;
            })}
        </>
    );
}

function BlockEl({
                     block,
                     onInlineLinkClick,
                 }: {
    block: Block;
    onInlineLinkClick?: (href: string) => void;
}) {
    switch (block.type) {
        case "paragraph": {
            const children = (block as any).children || [];
            const isEmpty =
                !children || children.every((c: any) => ((c.text ?? "") as string).trim() === "");
            if (isEmpty) return <p className="leading-relaxed whitespace-pre-wrap">&nbsp;</p>;
            return (
                <p className="leading-relaxed whitespace-pre-wrap">
                    <Inline nodes={children} onLinkClick={onInlineLinkClick} />
                </p>
            );
        }

        case "heading": {
            const lvl = Math.min(Math.max(Number((block as any).level) || 2, 1), 6);
            const sizes: Record<number, string> = {
                1: "text-2xl sm:text-3xl font-bold",
                2: "text-xl sm:text-2xl font-bold",
                3: "text-lg sm:text-xl font-semibold",
                4: "text-base sm:text-lg font-semibold",
                5: "text-base font-semibold",
                6: "text-sm font-semibold",
            };
            const cls = sizes[lvl] ?? sizes[2];

            type HeadingTag = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
            const Tag = `h${lvl}` as HeadingTag;

            return (
                <Tag className={cls}>
                    <Inline nodes={(block as any).children || []} onLinkClick={onInlineLinkClick} />
                </Tag>
            );
        }

        case "bulleted-list":
        case "numbered-list": {
            const isNum = block.type === "numbered-list";
            const Tag = (isNum ? "ol" : "ul") as "ol" | "ul";

            return (
                <Tag className={`ml-5 ${isNum ? "list-decimal" : "list-disc"} space-y-1`}>
                    {(block.children || []).map((li, j) => (
                        <li key={j} className="leading-relaxed">
                            <Inline nodes={li.children || []} onLinkClick={onInlineLinkClick} />
                        </li>
                    ))}
                </Tag>
            );
        }

        default: {
            if ((block as any).children?.length) {
                return (
                    <p className="leading-relaxed whitespace-pre-wrap">
                        <Inline nodes={(block as any).children} onLinkClick={onInlineLinkClick} />
                    </p>
                );
            }
            return null;
        }
    }
}

function Blocks({
                    blocks = [] as Block[],
                    onInlineLinkClick,
                }: {
    blocks?: Block[];
    onInlineLinkClick?: (href: string) => void;
}) {
    return (
        <div className="space-y-3">
            {blocks.map((b, i) => (
                <BlockEl key={i} block={b} onInlineLinkClick={onInlineLinkClick} />
            ))}
        </div>
    );
}

/* =======================
   Types
   ======================= */
type PortfolioCard = {
    id: number | string;
    title: string;
    description?: unknown;
    video?: unknown;
    numer_sortowania?: number | null;
};

type PortfolioModalSettings = {
    hero_title?: string;
    hero_subtitle?: string;
    hero_image?: unknown;

    tytul_hero?: string;
    podtytul_hero?: string;

    footer_title?: string;
    footer_subtitle?: string;
    footer_button_label?: string;

    cta_link?: string;
    cta_mail?: string;
};

export default function PortfolioModalContent({ locale = "pl" }: { locale?: import("../../../lib/locale").SupportedLocale }) {
    // HOOKI zawsze w tej samej kolejności
    const [cards, setCards] = useState<PortfolioCard[]>([]);
    const [settings, setSettings] = useState<PortfolioModalSettings | null>(null);
    const [expandedIndex, setExpandedIndex] = useState<number | null>(null);

    // zarządzanie wideo: tylko jedno gra naraz
    const activeVideoIdRef = useRef<string | number | null>(null);
    const videoRefs = useRef<Record<string, HTMLVideoElement | null>>({});

    const pauseAllVideosExcept = (keepId: string | number | null) => {
        const keep = keepId == null ? null : String(keepId);

        Object.entries(videoRefs.current).forEach(([id, el]) => {
            if (!el) return;
            if (keep && id === keep) return;

            try {
                el.pause();
            } catch {}
        });
    };

    const handleStartVideo = async (cardId: string | number, title: string) => {
        pauseAllVideosExcept(cardId);

        const el = videoRefs.current[String(cardId)];
        if (!el) return;

        activeVideoIdRef.current = cardId;

        gaEvent("portfolio_video_play", {
            card_id: String(cardId),
            title,
        });

        try {
            await el.play();
        } catch {}
    };

    const handleToggleExpand = (index: number, cardId: string | number, title: string, source: "card" | "button") => {
        pauseAllVideosExcept(null);
        activeVideoIdRef.current = null;

        setExpandedIndex((prev) => {
            const next = prev === index ? null : index;
            gaEvent("portfolio_card_toggle", {
                card_id: String(cardId),
                title,
                state: next === null ? "collapsed" : "expanded",
                source,
            });
            return next;
        });
    };

    const handleInlineLinkClick = (href: string) => {
        gaEvent("portfolio_inline_link_click", { href });
    };

    useEffect(() => {
        const load = async () => {
            try {
                const [settingsData, cardsData] = await Promise.all([
                    getPortfolioModalSettings(locale),
                    getPortfolioCards(locale),
                ]);

                setSettings(settingsData || null);
                setCards(cardsData || []);
            } catch (e) {
                console.error("Portfolio modal load error:", e);
            }
        };

        load();

        return () => {
            pauseAllVideosExcept(null);
            activeVideoIdRef.current = null;
        };
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    // Track view
    useEffect(() => {
        if (!settings) return;
        gaEvent("portfolio_modal_view", {
            cards_count: cards.length,
        });
    }, [settings, cards.length]);

    const heroTitle = settings?.hero_title || settings?.tytul_hero || "Portfolio";
    const heroSubtitle =
        settings?.hero_subtitle || settings?.podtytul_hero || "Wybrane realizacje.";

    const heroMediaUrl = safeMediaUrl(settings?.hero_image);
    const heroIsVideo = heroMediaUrl ? isVideoUrl(heroMediaUrl) : false;

    const footerTitle = settings?.footer_title || "Chcesz zobaczyć więcej?";
    const footerSubtitle =
        settings?.footer_subtitle || "Skontaktuj się, a podeślę dodatkowe realizacje.";
    const footerButtonLabel = settings?.footer_button_label || "Kontakt";

    const footerHref = useMemo(() => {
        if (settings?.cta_link) return settings.cta_link;
        if (settings?.cta_mail) return `mailto:${settings.cta_mail}`;
        return "#";
    }, [settings?.cta_link, settings?.cta_mail]);

    return (
        <motion.div
            className="w-full max-w-5xl mx-auto bg-white/5 backdrop-blur-sm rounded-2xl overflow-hidden border border-white/10 shadow-2xl text-white"
            initial={{ opacity: 0, scale: 0.95, y: 30 }}
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.95, y: 30 }}
            transition={{ duration: 0.3, ease: "easeOut" }}
        >
            {/* HERO */}
            <div className="relative w-full h-48 sm:h-64">
                {heroMediaUrl ? (
                    heroIsVideo ? (
                        <video
                            src={heroMediaUrl}
                            autoPlay
                            muted
                            loop
                            playsInline
                            preload="metadata"
                            className="absolute inset-0 w-full h-full object-cover brightness-75"
                        />
                    ) : (
                        <Image
                            src={heroMediaUrl}
                            alt={heroTitle}
                            fill
                            priority
                            className="object-cover brightness-75"
                        />
                    )
                ) : (
                    <div className="absolute inset-0 w-full h-full bg-white/10" />
                )}

                <div className="absolute inset-0 bg-black/50" />
                <div className="absolute inset-0 flex flex-col items-center justify-center text-center px-4">
                    <h1 className="text-3xl sm:text-4xl font-bold">{heroTitle}</h1>
                    <p className="text-white/70 mt-2 text-sm sm:text-base max-w-md">
                        {heroSubtitle}
                    </p>
                </div>
            </div>

            {/* KARTY */}
            <div className="p-6 sm:p-8 grid grid-cols-1 sm:grid-cols-2 gap-6 items-start">
                {cards.map((item, index) => {
                    const title = item.title || "Bez tytułu";

                    const blocks = normalizeToBlocks(item.description);
                    const plain = blocksToPlainText(blocks);
                    const shortText = preview30(plain);
                    const longer = plain.length > 30;

                    const mediaUrl = safeMediaUrl(item.video);
                    const mediaIsVideo = mediaUrl ? isVideoUrl(mediaUrl) : false;

                    const isExpanded = expandedIndex === index;

                    return (
                        <motion.div
                            key={item.id ?? index}
                            initial="initial"
                            whileInView="animate"
                            viewport={{ once: true, amount: 0.2 }}
                            variants={fadeInUp}
                            transition={{ duration: 0.5, delay: 0.2 + index * 0.15 }}
                            className="bg-white/10 border border-white/10 rounded-xl overflow-hidden hover:bg-white/20 transition flex flex-col cursor-pointer"
                            onClick={() =>
                                longer && handleToggleExpand(index, item.id, title, "card")
                            }
                            role={longer ? "button" : undefined}
                            tabIndex={longer ? 0 : -1}
                            onKeyDown={(e) => {
                                if (!longer) return;
                                if (e.key === "Enter" || e.key === " ") {
                                    e.preventDefault();
                                    handleToggleExpand(index, item.id, title, "card");
                                }
                            }}
                        >
                            <div className="relative w-full h-40 sm:h-52">
                                {mediaUrl ? (
                                    mediaIsVideo ? (
                                        <div
                                            className="absolute inset-0"
                                            onClick={(e) => {
                                                e.stopPropagation();
                                                handleStartVideo(item.id, title);
                                            }}
                                            role="button"
                                            tabIndex={0}
                                            onKeyDown={(e) => {
                                                if (e.key === "Enter" || e.key === " ") {
                                                    e.preventDefault();
                                                    handleStartVideo(item.id, title);
                                                }
                                            }}
                                        >
                                            <video
                                                ref={(el) => {
                                                    videoRefs.current[String(item.id)] = el;
                                                }}
                                                src={mediaUrl}
                                                controls
                                                playsInline
                                                preload="metadata"
                                                className="w-full h-full object-cover"
                                                onPlay={() => {
                                                    pauseAllVideosExcept(item.id);
                                                    activeVideoIdRef.current = item.id;
                                                }}
                                                onClick={(e) => e.stopPropagation()}
                                            />
                                        </div>
                                    ) : (
                                        <Image src={mediaUrl} alt={title} fill className="object-cover" />
                                    )
                                ) : (
                                    <div className="w-full h-full bg-white/10" />
                                )}
                            </div>

                            <div className="p-4 sm:p-6 flex flex-col flex-1">
                                <h3 className="text-lg sm:text-xl font-semibold mb-2">{title}</h3>

                                <AnimatePresence initial={false}>
                                    <motion.div
                                        key={isExpanded ? "expanded" : "collapsed"}
                                        initial={{ opacity: 0, height: 0 }}
                                        animate={{ opacity: 1, height: "auto" }}
                                        exit={{ opacity: 0, height: 0 }}
                                        transition={{ duration: 0.3, ease: "easeInOut" }}
                                        className="overflow-hidden text-white/80 text-sm leading-relaxed mb-2"
                                    >
                                        {isExpanded ? (
                                            <Blocks blocks={blocks} onInlineLinkClick={handleInlineLinkClick} />
                                        ) : (
                                            <p className="leading-relaxed">{shortText}</p>
                                        )}
                                    </motion.div>
                                </AnimatePresence>

                                {longer && (
                                    <button
                                        type="button"
                                        onClick={(e) => {
                                            e.stopPropagation();
                                            handleToggleExpand(index, item.id, title, "button");
                                        }}
                                        className="mt-auto text-[#eea71f] text-sm font-semibold self-start"
                                    >
                                        {isExpanded ? "Zwiń" : "Czytaj więcej"}
                                    </button>
                                )}
                            </div>
                        </motion.div>
                    );
                })}
            </div>

            {/* CTA / STOPKA */}
            <motion.div
                className="text-center px-6 pb-8"
                initial="initial"
                whileInView="animate"
                viewport={{ once: true, amount: 0.2 }}
                variants={fadeInUp}
                transition={{ duration: 0.5, delay: 0.2 }}
            >
                <h2 className="text-xl sm:text-2xl font-bold mb-3">{footerTitle}</h2>
                <p className="text-white/70 max-w-md mx-auto text-sm sm:text-base mb-6">
                    {footerSubtitle}
                </p>

                <a
                    href={footerHref}
                    className="text-sm font-medium text-[#eea71f] border border-[#eea71f] px-5 py-2 rounded-full hover:bg-[#eea71f]/10 transition duration-300 ease-in-out cursor-pointer"
                    onClick={(e) => {
                        e.stopPropagation();
                        gaEvent("portfolio_cta_click", {
                            href: footerHref,
                            label: footerButtonLabel,
                        });
                    }}
                >
                    {footerButtonLabel}
                </a>
            </motion.div>
        </motion.div>
    );
}
