import { Link } from "react-router-dom";
import { motion } from "framer-motion";
import { looksLikeImageUrl } from "@/lib/contentFormUtils";
import { MONTH_TIMELINE } from "./defaults";
import type { CompetitionItem, CompetitionPanelContent } from "./types";

const colorMap: Record<string, string> = {
    "deep-sea": "border-deep-sea bg-deep-sea/10",
    valencia: "border-valencia bg-valencia/10",
    moss: "border-moss bg-moss/10",
    sunflower: "border-sunflower bg-sunflower/10",
    salmon: "border-salmon bg-salmon/10",
    mist: "border-mist bg-mist/10",
};

const dotMap: Record<string, string> = {
    "deep-sea": "bg-deep-sea",
    valencia: "bg-valencia",
    moss: "bg-moss",
    sunflower: "bg-sunflower",
    salmon: "bg-salmon",
    mist: "bg-mist",
};

const accentClassMap: Record<string, string> = {
    primary: "text-primary border-primary",
    "deep-sea": "text-deep-sea border-deep-sea",
    valencia: "text-valencia border-valencia",
    moss: "text-moss border-moss",
    sunflower: "text-sunflower border-sunflower",
    salmon: "text-salmon border-salmon",
    mist: "text-mist border-mist",
};

type MonthGroup = { month: string; comps: CompetitionItem[] };

function getMonthBucket(month?: string): string | null {
    if (!month) return null;
    const value = month.toLowerCase();
    for (const candidate of MONTH_TIMELINE) {
        if (value.includes(candidate.toLowerCase())) return candidate;
    }
    return null;
}

export function countRenderableCompetitions(panel: CompetitionPanelContent): number {
    return panel.competitions.filter(
        (item) => item.title || item.description || item.category || item.month,
    ).length;
}

function groupByMonth(comps: CompetitionItem[]): { timeline: MonthGroup[]; flexible: CompetitionItem[] } {
    const groups: Record<string, CompetitionItem[]> = {};
    const flexible: CompetitionItem[] = [];

    for (const competition of comps) {
        const field = competition.month || competition.orionMonth;
        if (!field) {
            flexible.push(competition);
            continue;
        }

        const months = field
            .split(",")
            .map((part) => part.trim())
            .filter(Boolean);
        let matched = false;
        for (const month of months) {
            const bucket = getMonthBucket(month);
            if (!bucket) continue;
            matched = true;
            if (!groups[bucket]) groups[bucket] = [];
            groups[bucket].push(competition);
        }
        if (!matched) flexible.push(competition);
    }

    const timeline = MONTH_TIMELINE.filter((month) => groups[month]).map((month) => ({
        month,
        comps: groups[month],
    }));

    return { timeline, flexible };
}

function CompIcon({ icon, iconImage }: { icon: string; iconImage: string }) {
    if (iconImage && looksLikeImageUrl(iconImage)) {
        return <img src={iconImage} alt="" className="w-5 h-5 object-contain shrink-0" />;
    }
    if (icon) {
        return <span className="text-base leading-none">{icon}</span>;
    }
    return null;
}

function isExternalUrl(url: string): boolean {
    return (
        /^https?:\/\//i.test(url) ||
        url.startsWith("//") ||
        url.startsWith("mailto:") ||
        url.startsWith("tel:")
    );
}

function CompCard({ comp }: { comp: CompetitionItem }) {
    const borderClass = colorMap[comp.color] ?? colorMap["deep-sea"];
    const hasIcon = Boolean(comp.iconImage || comp.icon);
    const hasTags =
        Boolean(comp.publicTiming) ||
        Boolean(comp.orionMonth) ||
        Boolean(comp.dateTime) ||
        Boolean(comp.method) ||
        Boolean(comp.badge);
    const hasButton = Boolean(comp.buttonText);

    return (
        <div
            className={`rounded-xl border-l-4 ${borderClass} bg-card p-4 shadow-sm hover:shadow-md transition-shadow`}
        >
            <div className="flex items-center gap-2 mb-1">
                {hasIcon ? <CompIcon icon={comp.icon} iconImage={comp.iconImage} /> : null}
                {comp.title ? (
                    <h3 className="font-display text-sm font-bold text-foreground">{comp.title}</h3>
                ) : null}
            </div>
            {comp.category ? (
                <p className="text-[0.65rem] text-muted-foreground font-display mb-1.5">{comp.category}</p>
            ) : null}
            {comp.description ? (
                <p className="text-xs text-muted-foreground leading-relaxed mb-2">{comp.description}</p>
            ) : null}
            {comp.publicCompetition ? (
                <p className="text-xs text-foreground/80 mb-1.5">
                    <span className="text-muted-foreground">Public: </span>
                    {comp.publicCompetition}
                </p>
            ) : null}
            {hasTags ? (
                <div className="flex flex-wrap gap-1.5 mt-2">
                    {comp.badge ? (
                        <span className="text-[0.6rem] bg-primary/10 text-primary px-2 py-0.5 rounded-full font-display">
                            {comp.badge}
                        </span>
                    ) : null}
                    {comp.publicTiming ? (
                        <span className="text-[0.6rem] bg-muted text-muted-foreground px-2 py-0.5 rounded-full font-display">
                            📅 Public: {comp.publicTiming}
                        </span>
                    ) : null}
                    {comp.orionMonth ? (
                        <span className="text-[0.6rem] bg-primary/10 text-primary px-2 py-0.5 rounded-full font-display">
                            🏫 Orion: {comp.orionMonth}
                        </span>
                    ) : null}
                    {comp.dateTime ? (
                        <span className="text-[0.6rem] bg-muted text-muted-foreground px-2 py-0.5 rounded-full font-display">
                            🕐 {comp.dateTime}
                        </span>
                    ) : null}
                    {comp.method ? (
                        <span className="text-[0.6rem] bg-muted text-muted-foreground px-2 py-0.5 rounded-full font-display">
                            📋 {comp.method}
                        </span>
                    ) : null}
                </div>
            ) : null}
            {hasButton ? (
                <div className="mt-3">
                    {comp.buttonUrl ? (
                        isExternalUrl(comp.buttonUrl) ? (
                            <a
                                href={comp.buttonUrl}
                                target="_blank"
                                rel="noopener noreferrer"
                                className="inline-flex items-center font-display text-xs font-bold text-primary hover:underline"
                            >
                                {comp.buttonText}
                            </a>
                        ) : (
                            <Link
                                to={comp.buttonUrl}
                                className="inline-flex items-center font-display text-xs font-bold text-primary hover:underline"
                            >
                                {comp.buttonText}
                            </Link>
                        )
                    ) : (
                        <span className="inline-flex items-center font-display text-xs font-bold text-primary">
                            {comp.buttonText}
                        </span>
                    )}
                </div>
            ) : null}
        </div>
    );
}

type CompetitionTimelinePanelProps = {
    panel: CompetitionPanelContent;
    /** When true, omit outer section padding/container (parent already provides them). */
    embedded?: boolean;
};

export function CompetitionTimelinePanel({ panel, embedded = false }: CompetitionTimelinePanelProps) {
    const accentClass = accentClassMap[panel.accentColor] ?? accentClassMap.primary;
    const { timeline, flexible } = groupByMonth(panel.competitions);
    const hasTimeline = timeline.length > 0;
    const hasFlexible = flexible.length > 0;
    const showFlexibleLabel = Boolean(panel.flexibleEmoji || panel.flexibleTitle);

    const body = (
        <div>
            <div className="flex items-center gap-3 mb-8 justify-center">
                <div className="h-px flex-1 bg-border" />
                <span className={`font-display text-lg font-bold ${accentClass}`}>
                    {panel.emoji ? `${panel.emoji} ` : ""}
                    {panel.title}
                </span>
                <div className="h-px flex-1 bg-border" />
            </div>

            {panel.subtitle ? (
                <p
                    className={`font-display text-sm text-muted-foreground text-center ${
                        panel.description ? "mb-2" : "mb-8"
                    }`}
                >
                    {panel.subtitle}
                </p>
            ) : null}
            {panel.description ? (
                <p className="text-sm text-muted-foreground text-center leading-relaxed mb-8 max-w-2xl mx-auto">
                    {panel.description}
                </p>
            ) : null}

            {hasTimeline ? (
                <div className="relative">
                    <div className="absolute left-6 md:left-1/2 top-0 bottom-0 w-0.5 bg-border md:-translate-x-1/2" />
                    <div className="flex flex-col gap-10">
                        {timeline.map((group, groupIndex) => (
                            <div key={group.month} className="relative">
                                <motion.div
                                    initial={{ opacity: 0, scale: 0.8 }}
                                    whileInView={{ opacity: 1, scale: 1 }}
                                    viewport={{ once: true }}
                                    className="relative z-10 flex md:justify-center mb-4"
                                >
                                    <div className="ml-1 md:ml-0">
                                        <span
                                            className={`inline-block font-display text-xs font-bold px-3 py-1 rounded-full border ${accentClass} bg-background`}
                                        >
                                            {group.month}
                                        </span>
                                    </div>
                                </motion.div>

                                <div className="flex flex-col gap-4">
                                    {group.comps.map((comp, cardIndex) => {
                                        const side = (groupIndex + cardIndex) % 2 === 0 ? "left" : "right";
                                        const cardKey = `${comp.title}-${group.month}-${cardIndex}`;
                                        const dotClass = dotMap[comp.color] ?? dotMap["deep-sea"];

                                        return (
                                            <div key={cardKey} className="relative">
                                                <div className="hidden md:flex w-full items-start">
                                                    {side === "left" ? (
                                                        <>
                                                            <motion.div
                                                                className="w-[calc(50%-1.5rem)] flex justify-end"
                                                                initial={{ opacity: 0, x: -20 }}
                                                                whileInView={{ opacity: 1, x: 0 }}
                                                                viewport={{ once: true }}
                                                                transition={{ delay: cardIndex * 0.05 }}
                                                            >
                                                                <div className="max-w-sm w-full">
                                                                    <CompCard comp={comp} />
                                                                </div>
                                                            </motion.div>
                                                            <div className="w-12 flex justify-center relative z-10 pt-4">
                                                                <div
                                                                    className={`w-3 h-3 rounded-full ${dotClass} border-2 border-background`}
                                                                />
                                                            </div>
                                                            <div className="w-[calc(50%-1.5rem)]" />
                                                        </>
                                                    ) : (
                                                        <>
                                                            <div className="w-[calc(50%-1.5rem)]" />
                                                            <div className="w-12 flex justify-center relative z-10 pt-4">
                                                                <div
                                                                    className={`w-3 h-3 rounded-full ${dotClass} border-2 border-background`}
                                                                />
                                                            </div>
                                                            <motion.div
                                                                className="w-[calc(50%-1.5rem)] flex justify-start"
                                                                initial={{ opacity: 0, x: 20 }}
                                                                whileInView={{ opacity: 1, x: 0 }}
                                                                viewport={{ once: true }}
                                                                transition={{ delay: cardIndex * 0.05 }}
                                                            >
                                                                <div className="max-w-sm w-full">
                                                                    <CompCard comp={comp} />
                                                                </div>
                                                            </motion.div>
                                                        </>
                                                    )}
                                                </div>

                                                <motion.div
                                                    className="md:hidden flex items-start"
                                                    initial={{ opacity: 0, x: 15 }}
                                                    whileInView={{ opacity: 1, x: 0 }}
                                                    viewport={{ once: true }}
                                                >
                                                    <div className="w-12 flex justify-center relative z-10 pt-4">
                                                        <div
                                                            className={`w-3 h-3 rounded-full ${dotClass} border-2 border-background`}
                                                        />
                                                    </div>
                                                    <div className="flex-1">
                                                        <CompCard comp={comp} />
                                                    </div>
                                                </motion.div>
                                            </div>
                                        );
                                    })}
                                </div>
                            </div>
                        ))}
                    </div>
                </div>
            ) : null}

            {hasFlexible ? (
                <div className={hasTimeline ? "mt-16" : undefined}>
                    {showFlexibleLabel ? (
                        <div className="flex items-center gap-3 mb-6 justify-center">
                            <div className="h-px flex-1 bg-border" />
                            <span className="font-display text-sm font-bold text-muted-foreground">
                                {panel.flexibleEmoji ? `${panel.flexibleEmoji} ` : ""}
                                {panel.flexibleTitle}
                            </span>
                            <div className="h-px flex-1 bg-border" />
                        </div>
                    ) : null}
                    <div className="grid sm:grid-cols-2 gap-4 max-w-2xl mx-auto">
                        {flexible.map((comp, index) => (
                            <motion.div
                                key={`${comp.title}-flexible-${index}`}
                                initial={{ opacity: 0, y: 15 }}
                                whileInView={{ opacity: 1, y: 0 }}
                                viewport={{ once: true }}
                                transition={{ delay: index * 0.05 }}
                            >
                                <CompCard comp={comp} />
                            </motion.div>
                        ))}
                    </div>
                </div>
            ) : null}
        </div>
    );

    if (embedded) {
        return body;
    }

    return (
        <section className="py-16 bg-background">
            <div className="container mx-auto px-6 max-w-4xl">{body}</div>
        </section>
    );
}
