import React, { useEffect, useState } from "react";
import {
  Chart as ChartJS,
  TimeScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Filler,
} from "chart.js";
import "chartjs-adapter-date-fns";
import { fr } from "date-fns/locale";
import annotationPlugin from "chartjs-plugin-annotation";
import { Line } from "react-chartjs-2";
import * as api from "../../api/client";

// Enregistrer les composants Chart.js
ChartJS.register(
  TimeScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Filler,
  annotationPlugin
);

// Couleurs Gruvbox
const COLORS = {
  green: "#b8bb26",
  yellow: "#fabd2f",
  red: "#fb4934",
  orange: "#fe8019",
  text: "#ebdbb2",
  muted: "#928374",
  bg: "#282828",
  purple: "#d3869b",
};

// Périodes disponibles
const PERIODS = [
  { label: "7j", days: 7 },
  { label: "30j", days: 30 },
  { label: "90j", days: 90 },
  { label: "Tout", days: 365 },
];

// Convertit une date UTC (sans timezone) en objet Date local
const parseUTCDate = (dateStr) => {
  if (!dateStr) return null;
  // Si la date n'a pas de timezone, on ajoute Z pour indiquer UTC
  const normalized = dateStr.endsWith("Z") || dateStr.includes("+") ? dateStr : dateStr + "Z";
  return new Date(normalized);
};

const formatDateLabel = (dateStr, spanDays) => {
  const date = parseUTCDate(dateStr);
  if (!date) return "-";

  // Adapter le format selon l'écart réel entre les dates
  if (spanDays < 1) {
    // Moins d'un jour : afficher uniquement l'heure
    return date.toLocaleTimeString("fr-FR", { hour: "2-digit", minute: "2-digit" });
  } else if (spanDays <= 7) {
    // 1 à 7 jours : afficher date + heure
    return date.toLocaleDateString("fr-FR", {
      day: "2-digit",
      month: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
    });
  } else {
    // Plus de 7 jours : afficher uniquement la date
    return date.toLocaleDateString("fr-FR", { day: "2-digit", month: "2-digit" });
  }
};

const formatPrice = (price) => {
  if (price == null) return "-";
  return new Intl.NumberFormat("fr-FR", {
    style: "currency",
    currency: "EUR",
  }).format(price);
};

const formatPriceShort = (price) => {
  if (price == null) return "-";
  return new Intl.NumberFormat("fr-FR", {
    style: "currency",
    currency: "EUR",
    maximumFractionDigits: 0,
  }).format(price);
};

const calculateTrend = (snapshots) => {
  if (!snapshots || snapshots.length < 2) {
    return { direction: "stable", percent: 0, color: COLORS.yellow, arrow: "→" };
  }

  const prices = snapshots
    .filter((s) => s.prix_actuel != null)
    .map((s) => s.prix_actuel);

  if (prices.length < 2) {
    return { direction: "stable", percent: 0, color: COLORS.yellow, arrow: "→" };
  }

  const first = prices[prices.length - 1]; // Le plus ancien
  const last = prices[0]; // Le plus récent
  const percentChange = ((last - first) / first) * 100;

  if (percentChange < -2) {
    return { direction: "down", percent: percentChange, color: COLORS.green, arrow: "↓" };
  } else if (percentChange > 2) {
    return { direction: "up", percent: percentChange, color: COLORS.red, arrow: "↑" };
  }
  return { direction: "stable", percent: percentChange, color: COLORS.yellow, arrow: "→" };
};

const PriceChart = ({ productId, prixConseille, prixMin30j }) => {
  const [snapshots, setSnapshots] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [selectedPeriod, setSelectedPeriod] = useState(30);

  useEffect(() => {
    const fetchSnapshots = async () => {
      try {
        setLoading(true);
        const data = await api.fetchSnapshots(productId, selectedPeriod);
        setSnapshots(data);
        setError(null);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchSnapshots();
  }, [productId, selectedPeriod]);

  if (loading) {
    return (
      <div className="price-chart-loading">
        <i className="fa-solid fa-spinner fa-spin"></i>
      </div>
    );
  }

  if (error) {
    return <div className="price-chart-error">Erreur: {error}</div>;
  }

  if (!snapshots || snapshots.length === 0) {
    return (
      <div className="price-chart-empty">
        <i className="fa-solid fa-chart-line"></i>
        <span>Pas encore de données</span>
      </div>
    );
  }

  // Préparer les données (inverser pour ordre chronologique)
  const sortedSnapshots = [...snapshots].reverse();

  // Calculer le span réel entre la première et dernière date
  let spanDays = 0;
  if (sortedSnapshots.length >= 2) {
    const firstDate = parseUTCDate(sortedSnapshots[0].scrape_le);
    const lastDate = parseUTCDate(sortedSnapshots[sortedSnapshots.length - 1].scrape_le);
    if (firstDate && lastDate) {
      spanDays = (lastDate - firstDate) / (1000 * 60 * 60 * 24);
    }
  }

  // Données au format {x: Date, y: prix} pour TimeScale
  const chartPoints = sortedSnapshots
    .filter((s) => s.prix_actuel != null)
    .map((s) => ({
      x: parseUTCDate(s.scrape_le),
      y: s.prix_actuel,
    }));

  const prices = chartPoints.map((p) => p.y);

  // Calculer min/max
  const validPrices = prices.filter((p) => p != null);
  const minPrice = Math.min(...validPrices);
  const maxPrice = Math.max(...validPrices);

  // Calculer la tendance
  const trend = calculateTrend(snapshots);

  // Préparer les annotations (lignes de référence)
  const annotations = {};

  // Ligne prix conseillé (si disponible et dans une plage raisonnable)
  if (prixConseille && prixConseille > maxPrice * 0.8) {
    annotations.prixConseille = {
      type: "line",
      yMin: prixConseille,
      yMax: prixConseille,
      borderColor: COLORS.muted,
      borderWidth: 1,
      borderDash: [5, 5],
      label: {
        display: true,
        content: `Conseillé ${formatPriceShort(prixConseille)}`,
        position: "end",
        backgroundColor: "transparent",
        color: COLORS.muted,
        font: { size: 9 },
      },
    };
  }

  // Ligne prix min 30j (si disponible)
  if (prixMin30j && prixMin30j <= minPrice * 1.1) {
    annotations.prixMin30j = {
      type: "line",
      yMin: prixMin30j,
      yMax: prixMin30j,
      borderColor: COLORS.green,
      borderWidth: 1,
      borderDash: [3, 3],
      label: {
        display: true,
        content: `Min 30j ${formatPriceShort(prixMin30j)}`,
        position: "start",
        backgroundColor: "transparent",
        color: COLORS.green,
        font: { size: 9 },
      },
    };
  }

  const chartData = {
    datasets: [
      {
        data: chartPoints,
        borderColor: trend.color,
        backgroundColor: `${trend.color}20`,
        fill: true,
        tension: 0.3,
        pointRadius: 3,
        pointHoverRadius: 5,
        pointBackgroundColor: trend.color,
        pointBorderColor: trend.color,
      },
    ],
  };

  // Déterminer l'unité de temps appropriée selon la période
  const getTimeUnit = () => {
    if (spanDays < 1) return "hour";
    if (spanDays <= 7) return "day";
    if (spanDays <= 90) return "week";
    return "month";
  };

  const chartOptions = {
    responsive: true,
    maintainAspectRatio: false,
    plugins: {
      legend: {
        display: false,
      },
      tooltip: {
        backgroundColor: COLORS.bg,
        titleColor: COLORS.text,
        bodyColor: COLORS.text,
        borderColor: COLORS.muted,
        borderWidth: 1,
        padding: 10,
        callbacks: {
          title: (context) => {
            const date = context[0]?.raw?.x;
            if (!date) return "";
            return date.toLocaleDateString("fr-FR", {
              day: "2-digit",
              month: "2-digit",
              year: "numeric",
              hour: "2-digit",
              minute: "2-digit",
            });
          },
          label: (context) => formatPrice(context.raw?.y),
        },
      },
      annotation: {
        annotations,
      },
    },
    scales: {
      x: {
        type: "time",
        time: {
          unit: getTimeUnit(),
          displayFormats: {
            hour: "HH:mm",
            day: "dd/MM",
            week: "dd/MM",
            month: "MMM yyyy",
          },
        },
        adapters: {
          date: {
            locale: fr,
          },
        },
        grid: {
          display: false,
        },
        ticks: {
          color: COLORS.muted,
          font: { size: 10 },
          maxRotation: 0,
          maxTicksLimit: 6,
        },
      },
      y: {
        grid: {
          color: `${COLORS.muted}30`,
        },
        ticks: {
          color: COLORS.muted,
          font: { size: 10 },
          callback: (value) => formatPriceShort(value),
        },
        // Étendre l'échelle Y pour inclure le prix conseillé si présent
        suggestedMax: prixConseille ? Math.max(maxPrice, prixConseille) * 1.02 : undefined,
      },
    },
  };

  const lastSnapshot = snapshots[0];
  const lastDate = lastSnapshot
    ? parseUTCDate(lastSnapshot.scrape_le).toLocaleDateString("fr-FR", {
        day: "2-digit",
        month: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
      })
    : "-";

  return (
    <div className="price-chart-container">
      {/* Sélecteur de période */}
      <div className="price-chart-period-selector">
        {PERIODS.map((p) => (
          <button
            key={p.days}
            className={`period-btn ${selectedPeriod === p.days ? "active" : ""}`}
            onClick={() => setSelectedPeriod(p.days)}
          >
            {p.label}
          </button>
        ))}
      </div>

      <div className="price-chart">
        <Line data={chartData} options={chartOptions} />
      </div>
      <div className="price-chart-stats">
        <span className="stat">
          <span className="label">Min</span>
          <span className="value">{formatPrice(minPrice)}</span>
        </span>
        <span className="stat">
          <span className="label">Max</span>
          <span className="value">{formatPrice(maxPrice)}</span>
        </span>
        <span className="stat trend" style={{ color: trend.color }}>
          <span className="label">Tendance</span>
          <span className="value">
            {trend.arrow} {trend.percent >= 0 ? "+" : ""}
            {trend.percent.toFixed(1)}%
          </span>
        </span>
        <span className="stat">
          <span className="label">Dernier</span>
          <span className="value">{lastDate}</span>
        </span>
      </div>
    </div>
  );
};

export default PriceChart;
