pages/experience/Experience.jsx

import {useTranslation} from "react-i18next";
import React, {useEffect, useMemo, useState} from "react";
import {Card} from "@/components/ui/card/Card";
import {CardContent} from "@/components/ui/cardContent/CardContent";
import {PageSection} from "@/components/ui/pageSection/PageSection";
import {ExpandableText} from "@/components/ui/expandableText/ExpandableText";
import {SeoHead} from "@/components/seoHead/SeoHead";
import {SelectableButton} from "@/components/ui/selectableButton/SelectableButton";
import {PageGrid} from "@/components/ui/pageGrid/PageGrid";
import TechDisclosure from "@/components/ui/techDisclosure/TechDisclosure";
import {getExperiences} from "@/services/portfolioService";
import {Loading} from "@/components/loading/Loading";
import {ErrorState} from "@/components/errorState/ErrorState";

/**
 * Determines the experience label and type based on the selected year within a period string.
 *
 * Parses the given period string to extract start and end years, then compares with the selected year.
 * Returns an object with a localized label and a type indicating whether the year is at the start, end,
 * or the only year of the experience period.
 *
 * @param {string} period - The period string containing one or two years (e.g. "2019-2021" or "2020").
 * @param {string|number} year - The selected year to compare against the period.
 * @param {function} t - Translation function (e.g. from i18next) to get localized labels.
 * @returns {{label: string, type: "single" | "start" | "end"} | null}
 *          An object with the label and type if the selected year matches start/end/single year,
 *          or null if no match or invalid period.
 */
export const getExperienceLabel = (period, year, t) => {
    const years = period.match(/\b(20\d{2}|19\d{2})\b/g);
    const selected = parseInt(year, 10);

    if (!years) return null;

    const start = parseInt(years[0], 10);
    const end = years[1] ? parseInt(years[1], 10) : null;

    if (start === selected && end === selected) {
        return {label: t("exp_label_single"), type: "single"};
    }

    if (start === selected) {
        return {label: t("exp_label_start"), type: "start"};
    }

    if (end === selected) {
        return {label: t("exp_label_end"), type: "end"};
    }

    return null;
};

/**
 * Experience component renders a list of professional experiences filtered by selected year.
 *
 * It displays year buttons to filter experiences by year extracted from experience periods.
 * Each experience shows role, company, period, description, and a collapsible panel with technologies used.
 *
 * Uses i18next for translations.
 *
 * @component
 * @module pages/experience/Experience
 * @returns {JSX.Element} The rendered experience section with filtering and animated transitions.
 */
export default function Experience() {
    const {t} = useTranslation();

// --- State ---
    const [experiences, setExperiences] = useState([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    const [selectedYear, setSelectedYear] = useState(null);

// --- Data fetching ---
    const loadExperiences = () => {
        setLoading(true);
        setError(null);

        getExperiences()
            .then(setExperiences)
            .catch(setError)
            .finally(() => setLoading(false));
    };

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

// --- Derived data: list of years ---
    const yearList = useMemo(() => {
        const yearRegex = /\b(20\d{2}|19\d{2})\b/g;
        const years = new Set();

        experiences.forEach(exp => {
            const match = exp.period.match(yearRegex);
            if (match) {
                match.forEach(y => years.add(y));
            }
        });

        return Array.from(years).sort((a, b) => b - a);
    }, [experiences]);

// --- Auto-select latest year if none selected ---
    useEffect(() => {
        if (yearList.length > 0 && !selectedYear) {
            setSelectedYear(yearList[0]);
        }
    }, [yearList, selectedYear]);

// --- Filtered experiences by selected year ---
    const filteredExperiences = useMemo(() => {
        if (!selectedYear) return [];
        return experiences.filter(exp => exp.period.includes(selectedYear));
    }, [experiences, selectedYear]);

    if (loading) return <Loading/>;
    if (error) return <ErrorState message={t("error_generic")} onRetry={loadExperiences}/>;

    return (
        <>
            <SeoHead pageKey="experience" path="/experience"/>

            <PageSection title={t("experience_title")}>
                {/* Years */}
                <div className="mb-8">
                    <div
                        className="flex flex-row sm:flex-wrap sm:justify-center gap-2 sm:gap-3 overflow-x-auto sm:overflow-visible px-2 sm:px-0 pb-3 scrollbar-hide">
                        {yearList.map(year => (
                            <SelectableButton
                                key={year}
                                label={year}
                                isSelected={selectedYear === year}
                                onClick={() => setSelectedYear(year)}
                                className={`flex-shrink-0 transition-all duration-200 ${
                                    selectedYear === year
                                        ? "bg-blue-600 text-white shadow-md"
                                        : "bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-blue-500 hover:text-white"
                                }`}
                            />
                        ))}
                    </div>
                </div>

                {filteredExperiences.length > 0 && (
                    <PageGrid page={selectedYear} columns={2}>
                        {filteredExperiences.map((exp, i) => (
                            <Card
                                key={i}
                                className="relative w-full p-5 sm:p-6 border border-gray-200/60
                                           dark:border-gray-700/60 bg-white/60 dark:bg-gray-800/40 backdrop-blur-md
                                           rounded-xl hover:shadow-lg transition-all duration-300
                                           flex flex-col md:flex-row items-start gap-4"
                            >
                                <CardContent className="p-0">
                                    {/* Title and main info */}
                                    <div
                                        className="flex flex-col md:flex-row md:items-center md:justify-between gap-2 md:gap-4">
                                        <h3 className="text-lg md:text-xl font-semibold text-gray-900 dark:text-gray-100">
                                            {t(exp.role)}
                                        </h3>

                                        <div className="flex items-center gap-2 flex-wrap">
                                            <p className="text-gray-600 dark:text-gray-400">{exp.company}</p>
                                            {(() => {
                                                const status = getExperienceLabel(exp.period, selectedYear, t);
                                                if (!status) return null;

                                                const colorMap = {
                                                    start: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300",
                                                    end: "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300",
                                                    single: "bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-300",
                                                };

                                                return (
                                                    <span
                                                        className={`inline-block mt-1 px-2 py-0.5 text-xs font-semibold rounded-full ${colorMap[status.type]}`}
                                                    >
                                                {status.label}
                                            </span>
                                                );
                                            })()}
                                        </div>
                                    </div>

                                    {/* Period */}
                                    <p className="text-sm text-gray-500 dark:text-gray-400">{exp.period}</p>

                                    {/* Description */}
                                    {exp.description && (
                                        <ExpandableText
                                            value={t(exp.description)}
                                            maxLines={4}
                                            className="text-sm mb-2 px-4 py-3 bg-white/50 dark:bg-gray-900/50 rounded-xl shadow-inner italic text-gray-800 dark:text-gray-200"
                                        />
                                    )}

                                    {/* Tech */}
                                    <TechDisclosure techList={exp.tech} label={t("show_technologies")}/>

                                </CardContent>
                            </Card>
                        ))}
                    </PageGrid>
                )}
            </PageSection>
        </>
    );
}