"use client";

import { useState, useEffect, useCallback } from "react";
import {
  CreditCard, Save, Loader2, CheckCircle, XCircle,
  Zap, RefreshCw, ExternalLink, AlertTriangle, KeyRound,
  Crown, Building2, Sparkles
} from "lucide-react";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";
import { Separator } from "@/components/ui/separator";
import { useTranslationStore } from "@/lib/store";
import { API_BASE } from "@/lib/config";
import {
  ANNUAL_DISCOUNT_PERCENT,
  YEARLY_DISCOUNT_FACTOR,
  computeYearlyFromMonthly,
} from "@/lib/pricing";

/* ─── Types ─── */
interface PlanConfig {
  name: string;
  price_monthly: number;
  price_yearly: number;
  stripe_price_id_monthly: string;
  stripe_price_id_yearly: string;
}
interface PricingData {
  starter: PlanConfig;
  pro: PlanConfig;
  business: PlanConfig;
}
interface StripeStatus {
  configured: boolean;
  mode: "live" | "test" | "unknown";
  is_test_mode_in_production: boolean;
  has_secret_key: boolean;
  has_publishable_key: boolean;
  has_webhook_secret: boolean;
  publishable_key: string;
}

const PLAN_ICONS: Record<string, React.ElementType> = {
  starter: Zap,
  pro: Crown,
  business: Building2,
};

/** Le backend refuse les placeholders (xxx) — envoyer une chaîne vide pour ne pas bloquer la sauvegarde des prix. */
function sanitizeStripePriceIdForSave(raw: string): string {
  const s = raw.trim();
  if (!s) return "";
  const lower = s.toLowerCase();
  if (lower.includes("xxx") || lower.includes("placeholder")) return "";
  return s;
}

const EMPTY_PLAN: PlanConfig = {
  name: "",
  price_monthly: 0,
  price_yearly: 0,
  stripe_price_id_monthly: "",
  stripe_price_id_yearly: "",
};

/** Aligné sur models/subscription.py — éviter 0 € initial : le backend refuse < 0,01 € et la sauvegarde échouait pour Pro/Business. */
function defaultPricingData(): PricingData {
  const s = 9;
  const p = 19;
  const b = 49;
  return {
    starter: {
      ...EMPTY_PLAN,
      name: "Starter",
      price_monthly: s,
      price_yearly: computeYearlyFromMonthly(s),
    },
    pro: {
      ...EMPTY_PLAN,
      name: "Pro",
      price_monthly: p,
      price_yearly: computeYearlyFromMonthly(p),
    },
    business: {
      ...EMPTY_PLAN,
      name: "Business",
      price_monthly: b,
      price_yearly: computeYearlyFromMonthly(b),
    },
  };
}

export default function AdminPricingPage() {
  const [pricing, setPricing] = useState<PricingData>(defaultPricingData);
  const [stripeStatus, setStripeStatus] = useState<StripeStatus | null>(null);
  const [stripeKeys, setStripeKeys] = useState({
    secret: "",
    publishable: "",
    webhook: "",
  });
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [setupLoading, setSetupLoading] = useState(false);
  const [setupResult, setSetupResult] = useState<any>(null);
  const [webhookLoading, setWebhookLoading] = useState(false);
  const [webhookResult, setWebhookResult] = useState<any>(null);
  const [envMode, setEnvMode] = useState<string>("development");
  const [toast, setToast] = useState<{ type: "ok" | "err"; text: string } | null>(null);

  const getToken = () => useTranslationStore.getState().settings.adminToken ?? "";

  const showToast = (type: "ok" | "err", text: string) => {
    setToast({ type, text });
    setTimeout(() => setToast(null), 5000);
  };

  const loadPricing = useCallback(async () => {
    setLoading(true);
    try {
      const res = await fetch(`${API_BASE}/api/v1/admin/pricing`, {
        cache: "no-store",
        headers: { Authorization: `Bearer ${getToken()}` },
      });
      if (res.ok) {
        const j = await res.json();
        if (j.data) {
          const d = j.data as PricingData;
          (["starter", "pro", "business"] as const).forEach((pid) => {
            const m = d[pid].price_monthly;
            d[pid].price_yearly = computeYearlyFromMonthly(m);
          });
          setPricing(d);
        }
        if (j.stripe) setStripeStatus(j.stripe);
        if (j.meta?.env) setEnvMode(j.meta.env);
      } else if (res.status === 401) {
        showToast("err", "Session admin expirée. Reconnectez-vous.");
      } else {
        showToast("err", `Impossible de charger les tarifs (HTTP ${res.status}).`);
      }
    } catch {
      showToast("err", "Erreur réseau lors du chargement.");
    } finally {
      setLoading(false);
    }
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

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

  const parseApiError = async (res: Response): Promise<string> => {
    const err: {
      detail?: string | Array<{ msg?: string; type?: string }>;
      message?: string;
    } = await res.json().catch(() => ({}));
    if (Array.isArray(err.detail)) {
      return err.detail.map((e) => e.msg || JSON.stringify(e)).join(" — ") || `Erreur HTTP ${res.status}`;
    }
    if (typeof err.detail === "string") return err.detail;
    if (err.message) return err.message;
    return `Erreur HTTP ${res.status}`;
  };

  const savePricing = async () => {
    const token = useTranslationStore.getState().settings.adminToken;
    if (!token) {
      showToast("err", "Session admin absente. Reconnectez-vous sur /admin/login.");
      return;
    }

    for (const pid of ["starter", "pro", "business"] as const) {
      const m = pricing[pid].price_monthly;
      if (!Number.isFinite(m) || m < 0.01) {
        showToast(
          "err",
          `Prix mensuel invalide pour ${pricing[pid].name} : minimum 0,01 € (valeur actuelle : ${m}).`,
        );
        return;
      }
    }

    setSaving(true);
    try {
      const body: Record<string, unknown> = {
        starter: {
          price_monthly: pricing.starter.price_monthly,
          stripe_price_id_monthly: sanitizeStripePriceIdForSave(
            pricing.starter.stripe_price_id_monthly,
          ),
          stripe_price_id_yearly: sanitizeStripePriceIdForSave(
            pricing.starter.stripe_price_id_yearly,
          ),
        },
        pro: {
          price_monthly: pricing.pro.price_monthly,
          stripe_price_id_monthly: sanitizeStripePriceIdForSave(
            pricing.pro.stripe_price_id_monthly,
          ),
          stripe_price_id_yearly: sanitizeStripePriceIdForSave(
            pricing.pro.stripe_price_id_yearly,
          ),
        },
        business: {
          price_monthly: pricing.business.price_monthly,
          stripe_price_id_monthly: sanitizeStripePriceIdForSave(
            pricing.business.stripe_price_id_monthly,
          ),
          stripe_price_id_yearly: sanitizeStripePriceIdForSave(
            pricing.business.stripe_price_id_yearly,
          ),
        },
      };
      // Include Stripe keys only if filled in
      if (stripeKeys.secret) body.stripe_secret_key = stripeKeys.secret;
      if (stripeKeys.publishable) body.stripe_publishable_key = stripeKeys.publishable;
      if (stripeKeys.webhook) body.stripe_webhook_secret = stripeKeys.webhook;

      const res = await fetch(`${API_BASE}/api/v1/admin/pricing`, {
        method: "PUT",
        cache: "no-store",
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(body),
      });
      if (res.ok) {
        showToast("ok", "✅ Tarifs enregistrés (fichier data/pricing_overrides.json). Les clés Stripe vont dans .env si renseignées.");
        setStripeKeys({ secret: "", publishable: "", webhook: "" });
        loadPricing();
      } else {
        const msg = await parseApiError(res);
        showToast("err", msg);
      }
    } catch {
      showToast("err", "Erreur réseau (vérifiez que le backend tourne et que l’URL API est correcte).");
    } finally {
      setSaving(false);
    }
  };

  const autoSetupStripe = async () => {
    const token = useTranslationStore.getState().settings.adminToken;
    if (!token) {
      showToast("err", "Session admin absente. Reconnectez-vous.");
      return;
    }
    setSetupLoading(true);
    setSetupResult(null);
    try {
      const res = await fetch(`${API_BASE}/api/v1/admin/pricing/setup-stripe`, {
        method: "POST",
        cache: "no-store",
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
      });
      const j = await res.json();
      if (res.ok) {
        setSetupResult(j);
        if (j.errors?.length === 0) {
          showToast("ok", "✅ Produits Stripe créés et Price IDs enregistrés dans .env !");
        } else if (j.data && Object.keys(j.data).length > 0) {
          showToast("ok", `⚠️ Partiellement réussi. ${j.errors?.length} erreur(s).`);
        } else {
          showToast("err", j.errors?.[0]?.error || j.message || "Échec de la configuration Stripe.");
        }
        loadPricing();
      } else if (res.status === 409 && j.error === "TEST_MODE_IN_PRODUCTION") {
        // Give the user a way to override
        const ok = window.confirm(
          `${j.message}\n\nForcer la création en mode test ? (utile pour staging, à éviter en prod)`,
        );
        if (!ok) {
          setSetupResult(j);
          setSetupLoading(false);
          return;
        }
        const retry = await fetch(`${API_BASE}/api/v1/admin/pricing/setup-stripe`, {
          method: "POST",
          cache: "no-store",
          headers: {
            Authorization: `Bearer ${token}`,
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ force: true }),
        });
        const rj = await retry.json();
        setSetupResult(rj);
        if (retry.ok) {
          showToast("ok", "✅ Produits créés (forcé).");
          loadPricing();
        } else {
          showToast("err", rj.message || "Échec forcé.");
        }
      } else {
        showToast("err", j.message || "Erreur lors de la configuration Stripe.");
        setSetupResult(j);
      }
    } catch {
      showToast("err", "Erreur réseau.");
    } finally {
      setSetupLoading(false);
    }
  };

  const autoSetupWebhook = async () => {
    const token = useTranslationStore.getState().settings.adminToken;
    if (!token) {
      showToast("err", "Session admin absente. Reconnectez-vous.");
      return;
    }
    setWebhookLoading(true);
    setWebhookResult(null);
    try {
      const res = await fetch(`${API_BASE}/api/v1/admin/pricing/setup-webhook`, {
        method: "POST",
        cache: "no-store",
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
      });
      const j = await res.json();
      if (res.ok) {
        setWebhookResult(j);
        if (j.data?.secret_saved) {
          showToast("ok", "✅ Webhook Stripe créé/mis à jour et signing secret enregistré.");
        } else {
          showToast("ok", "✅ Webhook Stripe mis à jour. (Secret inchangé — il existait déjà.)");
        }
        loadPricing();
      } else if (res.status === 409 && j.error === "TEST_MODE_IN_PRODUCTION") {
        const ok = window.confirm(
          `${j.message}\n\nForcer quand même ?`,
        );
        if (!ok) {
          setWebhookResult(j);
          setWebhookLoading(false);
          return;
        }
        const retry = await fetch(`${API_BASE}/api/v1/admin/pricing/setup-webhook`, {
          method: "POST",
          cache: "no-store",
          headers: {
            Authorization: `Bearer ${token}`,
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ force: true }),
        });
        const rj = await retry.json();
        setWebhookResult(rj);
        if (retry.ok) {
          showToast("ok", "✅ Webhook créé (forcé).");
          loadPricing();
        } else {
          showToast("err", rj.message || "Échec forcé.");
        }
      } else {
        showToast("err", j.message || "Erreur lors de la création du webhook.");
        setWebhookResult(j);
      }
    } catch {
      showToast("err", "Erreur réseau.");
    } finally {
      setWebhookLoading(false);
    }
  };

  const updatePlan = (planId: keyof PricingData, field: keyof PlanConfig, value: string | number) => {
    setPricing((prev) => {
      const next = { ...prev[planId], [field]: value } as PlanConfig;
      if (field === "price_monthly") {
        const m = typeof value === "number" ? value : parseFloat(String(value)) || 0;
        next.price_yearly = computeYearlyFromMonthly(m);
      }
      return { ...prev, [planId]: next };
    });
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center py-16">
        <Loader2 className="w-8 h-8 animate-spin text-muted-foreground" />
      </div>
    );
  }

  return (
    <div className="space-y-6 max-w-5xl">
      {/* Header */}
      <div className="flex items-center gap-3">
        <div className="w-10 h-10 bg-emerald-600/20 rounded-lg flex items-center justify-center">
          <CreditCard className="w-5 h-5 text-emerald-400" />
        </div>
        <div>
          <h1 className="text-xl font-semibold text-foreground">Pricing & Stripe</h1>
          <p className="text-sm text-muted-foreground">
            Gérez les prix des forfaits et la configuration Stripe. Enregistrer ici applique les tarifs tout de suite (API publique, checkout) —{" "}
            <strong className="text-foreground/90">aucun redémarrage du serveur requis</strong>.
          </p>
        </div>
      </div>

      {/* Toast */}
      {toast && (
        <div className={`flex items-start gap-3 p-4 rounded-xl border text-sm ${
          toast.type === "ok"
            ? "bg-emerald-900/20 border-emerald-600/30 text-emerald-300"
            : "bg-red-900/20 border-red-600/30 text-red-300"
        }`}>
          {toast.type === "ok" ? <CheckCircle className="w-4 h-4 flex-shrink-0 mt-0.5" /> : <XCircle className="w-4 h-4 flex-shrink-0 mt-0.5" />}
          <span className="flex-1">{toast.text}</span>
          <button onClick={() => setToast(null)}>✕</button>
        </div>
      )}

      {/* Stripe Status */}
      <Card>
        <CardHeader className="pb-3">
          <CardTitle className="text-base flex items-center gap-2">
            <Sparkles className="w-4 h-4 text-violet-400" />
            Statut Stripe
            {stripeStatus?.mode === "live" && (
              <Badge className="ml-2 bg-emerald-600/20 text-emerald-300 border-emerald-500/40 text-[10px]">
                ● LIVE
              </Badge>
            )}
            {stripeStatus?.mode === "test" && (
              <Badge className="ml-2 bg-amber-600/20 text-amber-300 border-amber-500/40 text-[10px]">
                ● TEST
              </Badge>
            )}
            {stripeStatus?.mode === "unknown" && (
              <Badge variant="outline" className="ml-2 text-muted-foreground text-[10px]">
                non configuré
              </Badge>
            )}
            <span className="ml-auto text-xs text-muted-foreground font-mono">
              ENV={envMode}
            </span>
          </CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          {/* BLOCKING warning if test mode in production */}
          {stripeStatus?.is_test_mode_in_production && (
            <div className="flex items-start gap-3 p-4 rounded-xl border-2 border-red-500/50 bg-red-900/20 text-sm">
              <AlertTriangle className="w-5 h-5 text-red-400 flex-shrink-0 mt-0.5" />
              <div className="flex-1">
                <p className="text-red-300 font-bold">
                  ⚠️ CLÉ STRIPE TEST EN PRODUCTION
                </p>
                <p className="text-red-400/90 text-xs mt-1 leading-relaxed">
                  <code className="bg-red-950/50 px-1.5 py-0.5 rounded text-red-200">ENV=production</code>{" "}
                  mais{" "}
                  <code className="bg-red-950/50 px-1.5 py-0.5 rounded text-red-200">STRIPE_SECRET_KEY</code>{" "}
                  commence par <code className="bg-red-950/50 px-1.5 py-0.5 rounded text-red-200">sk_test_…</code>.
                  Les paiements en prod ne fonctionneront PAS — soit tu remplaces par{" "}
                  <code className="bg-red-950/50 px-1.5 py-0.5 rounded text-red-200">sk_live_…</code> dans
                  .env.ionos, soit tu remets <code className="bg-red-950/50 px-1.5 py-0.5 rounded text-red-200">ENV=staging</code>.
                </p>
              </div>
            </div>
          )}

          <div className="grid grid-cols-3 gap-3">
            {[
              { label: "Clé secrète", ok: stripeStatus?.has_secret_key },
              { label: "Clé publique", ok: stripeStatus?.has_publishable_key },
              { label: "Webhook secret", ok: stripeStatus?.has_webhook_secret },
            ].map(({ label, ok }) => (
              <div key={label} className={`rounded-lg border p-3 flex items-center gap-2 ${
                ok ? "border-emerald-600/30 bg-emerald-900/10" : "border-red-600/30 bg-red-900/10"
              }`}>
                {ok
                  ? <CheckCircle className="w-4 h-4 text-emerald-400 flex-shrink-0" />
                  : <XCircle className="w-4 h-4 text-red-400 flex-shrink-0" />}
                <span className="text-sm">{label}</span>
              </div>
            ))}
          </div>

          <Separator />

          {/* Auto-setup button (products + prices) */}
          <div className="flex items-start gap-4">
            <div className="flex-1">
              <p className="text-sm font-medium text-foreground">1. Produits &amp; prix</p>
              <p className="text-xs text-muted-foreground mt-1">
                Crée automatiquement les 3 produits (Starter, Pro, Business) et les 6 prix (mensuel + annuel) dans votre compte Stripe, puis sauvegarde les Price IDs dans le .env.
              </p>
              {setupResult && (
                <div className="mt-2 p-3 rounded-lg bg-secondary/40 text-xs space-y-1">
                  {Object.entries(setupResult.data || {}).map(([plan, info]: any) => (
                    <div key={plan} className="flex items-center gap-2">
                      <CheckCircle className="w-3 h-3 text-emerald-400" />
                      <span className="capitalize font-medium">{plan}</span>
                      <span className="text-muted-foreground">— mensuel: <code>{info.monthly_price_id}</code></span>
                    </div>
                  ))}
                  {setupResult.errors?.map((e: any, i: number) => (
                    <div key={i} className="flex items-center gap-2 text-red-400">
                      <XCircle className="w-3 h-3" />
                      <span>{e.plan}: {e.error}</span>
                    </div>
                  ))}
                </div>
              )}
            </div>
            <Button
              onClick={autoSetupStripe}
              disabled={setupLoading || !stripeStatus?.has_secret_key}
              className="bg-violet-600 hover:bg-violet-500 gap-2 flex-shrink-0"
            >
              {setupLoading ? <Loader2 className="w-4 h-4 animate-spin" /> : <RefreshCw className="w-4 h-4" />}
              {setupLoading ? "Configuration…" : "Créer automatiquement"}
            </Button>
          </div>

          <Separator />

          {/* Auto-setup webhook */}
          <div className="flex items-start gap-4">
            <div className="flex-1">
              <p className="text-sm font-medium text-foreground">2. Webhook Stripe</p>
              <p className="text-xs text-muted-foreground mt-1">
                Crée ou met à jour l'endpoint webhook dans Stripe pointant sur ce backend, et enregistre automatiquement le <code className="text-foreground/80">whsec_…</code> dans le .env.
                L'URL est déduite de la requête courante (header Host + X-Forwarded-Proto).
              </p>
              {webhookResult?.data && (
                <div className="mt-2 p-3 rounded-lg bg-secondary/40 text-xs space-y-1">
                  <div className="flex items-center gap-2">
                    <CheckCircle className="w-3 h-3 text-emerald-400" />
                    <span>ID: <code>{webhookResult.data.id}</code></span>
                  </div>
                  <div className="flex items-center gap-2 text-muted-foreground">
                    <ExternalLink className="w-3 h-3" />
                    <span className="break-all">{webhookResult.data.url}</span>
                  </div>
                  <div className="text-muted-foreground">
                    Events: <code>{(webhookResult.data.enabled_events || []).length}</code> abonné(s)
                    {webhookResult.data.created ? " — endpoint créé" : " — endpoint mis à jour"}
                    {webhookResult.data.secret_saved ? " — secret enregistré" : " — secret déjà connu"}
                  </div>
                </div>
              )}
            </div>
            <Button
              onClick={autoSetupWebhook}
              disabled={webhookLoading || !stripeStatus?.has_secret_key}
              variant="outline"
              className="gap-2 flex-shrink-0 border-violet-500/40 text-violet-300 hover:bg-violet-500/10"
            >
              {webhookLoading ? <Loader2 className="w-4 h-4 animate-spin" /> : <RefreshCw className="w-4 h-4" />}
              {webhookLoading ? "Configuration…" : "Setup webhook auto"}
            </Button>
          </div>

          <Separator />

          {/* Manual Stripe keys */}
          <div>
            <p className="text-sm font-medium text-foreground mb-3">Clés Stripe (laisser vide pour garder les valeurs actuelles)</p>
            <div className="grid gap-3">
              <div className="space-y-1.5">
                <Label htmlFor="stripe-secret" className="text-xs text-muted-foreground">Clé secrète (sk_test_... ou sk_live_...)</Label>
                <Input
                  id="stripe-secret"
                  type="password"
                  placeholder={stripeStatus?.has_secret_key ? "Clé déjà configurée — laisser vide pour garder" : "sk_test_..."}
                  value={stripeKeys.secret}
                  onChange={e => setStripeKeys(prev => ({ ...prev, secret: e.target.value }))}
                />
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="stripe-pub" className="text-xs text-muted-foreground">Clé publique (pk_test_... ou pk_live_...)</Label>
                <Input
                  id="stripe-pub"
                  placeholder={stripeStatus?.has_publishable_key ? "Clé déjà configurée" : "pk_test_..."}
                  value={stripeKeys.publishable}
                  onChange={e => setStripeKeys(prev => ({ ...prev, publishable: e.target.value }))}
                />
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="stripe-webhook" className="text-xs text-muted-foreground">Webhook secret (whsec_...)</Label>
                <Input
                  id="stripe-webhook"
                  type="password"
                  placeholder={stripeStatus?.has_webhook_secret ? "Secret déjà configuré" : "whsec_..."}
                  value={stripeKeys.webhook}
                  onChange={e => setStripeKeys(prev => ({ ...prev, webhook: e.target.value }))}
                />
              </div>
            </div>
            <p className="text-xs text-muted-foreground mt-2 flex items-center gap-1">
              <ExternalLink className="w-3 h-3" />
              <a href="https://dashboard.stripe.com/apikeys" target="_blank" rel="noreferrer" className="underline hover:text-foreground">
                Obtenir vos clés sur dashboard.stripe.com/apikeys
              </a>
            </p>
          </div>
        </CardContent>
      </Card>

      {/* Plan pricing cards */}
      <div className="grid gap-4 md:grid-cols-3">
        {(["starter", "pro", "business"] as const).map((planId) => {
          const plan = pricing[planId];
          const Icon = PLAN_ICONS[planId] || Sparkles;
          const hasMonthlyId = plan.stripe_price_id_monthly && !plan.stripe_price_id_monthly.includes("xxx");
          const hasYearlyId = plan.stripe_price_id_yearly && !plan.stripe_price_id_yearly.includes("xxx");

          return (
            <Card key={planId} className={`${
              planId === "pro" ? "border-violet-500/30" :
              planId === "business" ? "border-emerald-500/30" : ""
            }`}>
              <CardHeader className="pb-3">
                <CardTitle className="text-sm flex items-center gap-2">
                  <Icon className={`w-4 h-4 ${
                    planId === "pro" ? "text-violet-400" :
                    planId === "business" ? "text-emerald-400" : "text-blue-400"
                  }`} />
                  {plan.name}
                  {hasMonthlyId && hasYearlyId
                    ? <Badge className="ml-auto text-xs bg-emerald-900/30 text-emerald-300 border-emerald-500/30">✓ Stripe OK</Badge>
                    : <Badge variant="outline" className="ml-auto text-xs text-amber-400 border-amber-500/30">Price IDs manquants</Badge>}
                </CardTitle>
              </CardHeader>
              <CardContent className="space-y-3">
                {/* Prices */}
                <div className="grid grid-cols-2 gap-2">
                  <div className="space-y-1">
                    <Label className="text-xs text-muted-foreground">Prix mensuel (€)</Label>
                    <Input
                      type="number"
                      min="0"
                      step="0.01"
                      value={plan.price_monthly}
                      onChange={e => updatePlan(planId, "price_monthly", parseFloat(e.target.value) || 0)}
                      className="h-8 text-sm"
                    />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs text-muted-foreground">
                      Prix annuel (€) — auto (−{ANNUAL_DISCOUNT_PERCENT} %)
                    </Label>
                    <Input
                      type="number"
                      readOnly
                      tabIndex={-1}
                      value={plan.price_yearly}
                      className="h-8 text-sm bg-muted/40 cursor-not-allowed"
                      aria-readonly
                    />
                  </div>
                </div>
                <p className="text-[10px] text-muted-foreground leading-tight">
                  Facturation annuelle = 12 × mensuel × {YEARLY_DISCOUNT_FACTOR} (équivalent −{ANNUAL_DISCOUNT_PERCENT} % vs 12 mois au tarif mensuel). Le serveur impose cette règle à l’enregistrement et pour Stripe.
                </p>

                <Separator />

                {/* Stripe Price IDs */}
                <div className="space-y-2">
                  <div className="space-y-1">
                    <Label className="text-xs text-muted-foreground flex items-center gap-1">
                      <KeyRound className="w-3 h-3" /> Price ID mensuel
                    </Label>
                    <Input
                      placeholder="price_..."
                      value={plan.stripe_price_id_monthly}
                      onChange={e => updatePlan(planId, "stripe_price_id_monthly", e.target.value)}
                      className={`h-8 text-xs font-mono ${hasMonthlyId ? "border-emerald-500/30" : "border-amber-500/30"}`}
                    />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs text-muted-foreground flex items-center gap-1">
                      <KeyRound className="w-3 h-3" /> Price ID annuel
                    </Label>
                    <Input
                      placeholder="price_..."
                      value={plan.stripe_price_id_yearly}
                      onChange={e => updatePlan(planId, "stripe_price_id_yearly", e.target.value)}
                      className={`h-8 text-xs font-mono ${hasYearlyId ? "border-emerald-500/30" : "border-amber-500/30"}`}
                    />
                  </div>
                </div>
              </CardContent>
            </Card>
          );
        })}
      </div>

      {/* Warning if Price IDs missing */}
      {["starter", "pro", "business"].some(p => {
        const plan = pricing[p as keyof PricingData];
        return !plan.stripe_price_id_monthly || plan.stripe_price_id_monthly.includes("xxx");
      }) && (
        <div className="flex items-start gap-3 p-4 rounded-xl border border-amber-500/30 bg-amber-900/10 text-sm">
          <AlertTriangle className="w-4 h-4 text-amber-400 flex-shrink-0 mt-0.5" />
          <div>
            <p className="text-amber-300 font-medium">Price IDs Stripe manquants</p>
            <p className="text-amber-400/80 text-xs mt-1">
              Cliquez sur <strong>"Créer automatiquement"</strong> pour que le backend crée les produits dans Stripe et remplisse les IDs automatiquement. Ou entrez-les manuellement depuis votre{" "}
              <a href="https://dashboard.stripe.com/products" target="_blank" rel="noreferrer" className="underline">
                tableau de bord Stripe
              </a>.
            </p>
          </div>
        </div>
      )}

      {/* Save button */}
      <div className="flex justify-end">
        <Button onClick={savePricing} disabled={saving} size="lg" className="gap-2">
          {saving ? <Loader2 className="w-4 h-4 animate-spin" /> : <Save className="w-4 h-4" />}
          {saving ? "Sauvegarde…" : "Sauvegarder la configuration"}
        </Button>
      </div>
    </div>
  );
}
