/* ============================================================
   app.jsx - composition root + Payload connectivity
   ============================================================ */
const helper = window.LPVContentHydration;

const FIXED_ACCENT = ["#4A78C9", "#3A5FA0", "#EEF3FB", "#DBE6F6"];
const FIXED_PAPER_TONE = {
  "--paper": "#FCFCFD",
  "--paper-2": "#F1F2F4",
  "--paper-3": "#E6E8EC",
};

const DEFAULT_CONTENT = {
  seo: {
    title: "Camille Roussel - Kinésithérapeute remplaçant à Lyon",
    description:
      "Masseur-kinésithérapeute D.E. disponible pour vos remplacements à Lyon et dans le Grand Lyon.",
  },
  identity: {
    brand: "Camille Roussel",
    brandSuffix: "M.K. D.E.",
    cabinet: "Cabinet Roussel",
    title: "Masseur-kinésithérapeute D.E.",
    shortTitle: "Kinésithérapeute remplaçant",
    adeli: "69 04 12 873",
    rpps: "",
    city: "Lyon",
    area: "Lyon - Grand Lyon (69)",
    phone: "06 00 00 00 00",
    email: "contact@camilleroussel-kine.fr",
    address: "14 rue de la République, 69002 Lyon",
    status: "Disponible",
    statusLong: "Disponible pour vos remplacements",
  },
  nav: [
    { label: "Disponibilités", href: "#disponibilites" },
    { label: "Demande", href: "#formulaire" },
    { label: "À propos", href: "#apropos" },
    { label: "Mentions légales", href: "#legal" },
  ],
  hero: {
    eyebrow: "Masseur-kinésithérapeute D.E. - n° ADELI 69 04 12 873",
    title: "Kinésithérapeute\nexpérimenté disponible\npour remplacements",
    lede:
      "Camille Roussel assure vos remplacements de masso-kinésithérapie à Lyon et dans le Grand Lyon - cabinets libéraux, hôpitaux et cliniques. Courte ou longue durée, installation immédiate sur votre patientèle.",
    primaryCta: "Voir mes disponibilités",
    primaryUrl: "#disponibilites",
    secondaryCta: "Contrat type (PDF)",
    portrait: "",
    portraitAlt: "Portrait de Camille Roussel",
    portraitPlaceholder: "Déposez un portrait",
    cabinetTag: "Masso-kinésithérapie - Lyon",
    metrics: [
      { label: "Zone", value: "Lyon - Grand Lyon (69)" },
      { label: "Durées", value: "1 jour -> 6 mois" },
      { label: "Exercice", value: "Libéral - Hospitalier" },
      { label: "Conventionnement", value: "Secteur 1 - RCP à jour" },
    ],
  },
  availability: {
    sectionNumber: "01",
    sectionTitle: "Disponibilités",
    title: "Réservez un créneau de remplacement.",
    lede:
      "Les jours marqués « libre » sont ouverts à la pré-réservation. Sélectionnez une date, choisissez un créneau, et confirmez votre demande en quelques secondes.",
    bookingTitle: "Réservation",
    emptyText:
      "Sélectionnez un jour marqué « libre » dans le calendrier pour voir les créneaux de remplacement disponibles, puis pré-réservez en un clic.",
    confirmCta: "Pré-réserver ce créneau",
    slots: [
      { id: "am", label: "Matin", time: "08:00 - 13:00" },
      { id: "pm", label: "Après-midi", time: "14:00 - 19:00" },
      { id: "full", label: "Journée complète", time: "08:00 - 19:00" },
    ],
  },
  request: {
    sectionNumber: "02",
    sectionTitle: "Demande de remplacement",
    title: "Décrivez votre besoin.",
    lede:
      "Cabinet, hôpital ou clinique : transmettez-moi les dates et le contexte du remplacement. Téléchargez le contrat type pour préparer la convention.",
    submitCta: "Envoyer ma demande de remplacement",
    privacyNote:
      "Réponse sous 24 h ouvrées. Vos données ne sont utilisées que pour le traitement de votre demande.",
    successTitle: "Demande envoyée",
    successText:
      "Je reviens vers vous sous 24 h ouvrées pour confirmer les modalités du remplacement.",
  },
  documents: {
    contractTitle: "Contrat type de remplacement",
    contractMeta: "Modèle de convention libérale - A4 - 1 page",
    contractNote: "À compléter avant signature",
    downloadCta: "Télécharger",
    piecesTitle: "Pièces à prévoir",
    pieces: [
      "Diplôme d'État de masseur-kinésithérapeute",
      "Attestation d'inscription à l'Ordre",
      "Attestation d'assurance RCP",
      "Justificatif n° ADELI / RPPS",
    ],
  },
  about: {
    sectionNumber: "03",
    sectionTitle: "À propos",
    title: "Une continuité de soins, pas un simple dépannage.",
    paragraphs: [
      "Diplômée d'État en 2017, j'exerce en libéral comme à l'hôpital. Je me suis spécialisée dans le remplacement pour offrir aux cabinets et aux services une transition fluide : prise en main rapide du logiciel, respect des protocoles en place et des habitudes de la patientèle.",
      "Autonome dès la première demi-journée, j'assure le suivi des dossiers, la facturation et la rétrocession dans les règles. Mon objectif : que votre absence ne se voie pas dans la qualité des soins.",
    ],
    mobilityTitle: "Mobilité",
    mobilityText:
      "Véhiculée, interventions possibles sur l'ensemble de la métropole lyonnaise. Déplacements à domicile assurés selon les besoins du cabinet.",
    specialties: [
      { title: "Rééducation orthopédique & post-opératoire", text: "Suites de chirurgie, prothèses, traumatologie du sport." },
      { title: "Kinésithérapie respiratoire", text: "Adulte et pédiatrique, désencombrement, BPCO." },
      { title: "Rééducation neurologique", text: "AVC, troubles de l'équilibre, maladies neuro-dégénératives." },
      { title: "Thérapie manuelle & sport", text: "Lombalgies, tendinopathies, reprise d'activité." },
    ],
    stats: [
      { value: "9", suffix: "", label: "années d'exercice" },
      { value: "40", suffix: "+", label: "structures accompagnées" },
      { value: "12", suffix: "k+", label: "séances réalisées" },
      { value: "100", suffix: "%", label: "RCP & Ordre à jour" },
    ],
  },
  legal: {
    sectionNumber: "04",
    sectionTitle: "Mentions légales",
    copyright: "© 2026 Camille Roussel - Masseur-kinésithérapeute D.E.",
    legalLine:
      "Site de démonstration. Mentions, SIRET, Ordre, assurance et hébergement à compléter avant publication.",
    items: [
      { label: "Éditeur du site", text: "Camille Roussel, masseur-kinésithérapeute D.E., entrepreneur individuel. 14 rue de la République, 69002 Lyon." },
      { label: "Identifiants", text: "SIRET 812 345 678 00019 - n° ADELI 69 04 12 873 - TVA non applicable, art. 293 B du CGI." },
      { label: "Ordre & assurance", text: "Inscrite au Conseil départemental de l'Ordre des MK du Rhône. Responsabilité civile professionnelle souscrite auprès de la MACSF." },
      { label: "Hébergement", text: "Site hébergé en France. Directeur de la publication : Camille Roussel." },
      { label: "Données personnelles", text: "Les informations transmises via le formulaire servent uniquement au traitement de votre demande de remplacement et ne sont jamais cédées." },
      { label: "Propriété & cookies", text: "L'ensemble des contenus est protégé. Le site ne dépose aucun cookie de mesure d'audience ni de traçage publicitaire." },
    ],
  },
  footer: {
    description:
      "Remplacements de masso-kinésithérapie à Lyon et dans le Grand Lyon. Libéral, hôpital, clinique.",
    designLine: "Design system Swiss - International Typographic Style",
  },
};

function isObject(value) {
  return value && typeof value === "object" && !Array.isArray(value);
}

function mergeContent(base, override) {
  if (!isObject(override)) return base;
  if (Array.isArray(base) || Array.isArray(override)) return override ?? base;
  return Object.keys({ ...base, ...override }).reduce((acc, key) => {
    const baseValue = base?.[key];
    const overrideValue = override?.[key];
    acc[key] =
      isObject(baseValue) && isObject(overrideValue)
        ? mergeContent(baseValue, overrideValue)
        : overrideValue ?? baseValue;
    return acc;
  }, {});
}

function readPreviewContent() {
  return helper?.readPreviewContent?.() || null;
}

function usePayloadContent() {
  const [staticContent, setStaticContent] = React.useState(DEFAULT_CONTENT);
  const [previewContent, setPreviewContent] = React.useState(() => readPreviewContent());

  React.useEffect(() => {
    const loadContent = helper?.loadStaticContent
      ? helper.loadStaticContent("content.json")
      : fetch(`content.json?v=${encodeURIComponent(Date.now().toString(36))}`, { cache: "no-store" })
          .then((response) => (response.ok ? response.json() : null));

    loadContent
      .then((content) => {
        if (isObject(content)) setStaticContent(mergeContent(DEFAULT_CONTENT, content));
      })
      .catch((error) => {
        console.error("[paramedical-interim] static content load failed", error);
      })
      .finally(() => {
        helper?.markReady?.();
        helper?.notifyPreviewReady?.();
      });
  }, []);

  React.useEffect(() => {
    helper?.bindPreviewUpdates?.({
      staticContent: {},
      applyContent: setPreviewContent,
      merge: (_staticContent, previewContent) => previewContent,
    });
  }, []);

  return mergeContent(staticContent, previewContent);
}

function App() {
  useRevealObserver();
  const content = usePayloadContent();
  const [booking, setBooking] = React.useState(null);

  React.useEffect(() => {
    document.title = content.seo?.title || DEFAULT_CONTENT.seo.title;
    const description = content.seo?.description || content.hero?.lede || "";
    let meta = document.querySelector('meta[name="description"]');
    if (!meta) {
      meta = document.createElement("meta");
      meta.setAttribute("name", "description");
      document.head.appendChild(meta);
    }
    meta.setAttribute("content", description);
  }, [content]);

  React.useEffect(() => {
    const root = document.documentElement;
    root.style.setProperty("--accent", FIXED_ACCENT[0]);
    root.style.setProperty("--accent-ink", FIXED_ACCENT[1]);
    root.style.setProperty("--accent-50", FIXED_ACCENT[2]);
    root.style.setProperty("--accent-100", FIXED_ACCENT[3]);
    Object.entries(FIXED_PAPER_TONE).forEach(([key, value]) => {
      root.style.setProperty(key, value);
    });
  }, []);

  return (
    <React.Fragment>
      <ScrollProgress />
      <Header content={content} />
      <main>
        <Hero content={content} />

        <section className="section" id="disponibilites">
          <div className="wrap">
            <SectionLabel
              num={content.availability?.sectionNumber || "01"}
              title={content.availability?.sectionTitle || "Disponibilités"}
            />
            <div style={{ maxWidth: 720, marginBottom: "var(--s7)" }}>
              <h2 className="h2 reveal">{content.availability?.title}</h2>
              <p className="lead reveal" style={{ marginTop: 16, transitionDelay: ".06s" }}>
                {content.availability?.lede}
              </p>
            </div>
            <AvailabilityCalendar content={content.availability} onBook={setBooking} />
          </div>
        </section>

        <section className="section section--alt" id="formulaire">
          <div className="wrap">
            <SectionLabel
              num={content.request?.sectionNumber || "02"}
              title={content.request?.sectionTitle || "Demande de remplacement"}
            />
            <div style={{ maxWidth: 720, marginBottom: "var(--s7)" }}>
              <h2 className="h2 reveal">{content.request?.title}</h2>
              <p className="lead reveal" style={{ marginTop: 16, transitionDelay: ".06s" }}>
                {content.request?.lede}
              </p>
            </div>
            <div className="form-wrap">
              <ReplacementForm content={content.request} prefill={booking} />
              <ContractDownload content={content.documents} />
            </div>
          </div>
        </section>

        <About content={content.about} />
        <Legal content={content.legal} />
        <PatternDetails content={content} />
      </main>
      <Footer content={content} />
    </React.Fragment>
  );
}

function PatternDetails({ content }) {
  const availability = content.availability || {};
  const request = content.request || {};
  const identity = content.identity || {};
  const legal = content.legal || {};
  const rows = [
    ["Titre court", identity.shortTitle],
    ["Ville", identity.city],
    ["Adresse", identity.address],
    ["ADELI", identity.adeli],
    ["RPPS", identity.rpps],
    ["Confirmation calendrier", availability.confirmCta],
    ["Succes formulaire", request.successTitle],
    ["Message succes", request.successText],
    ["Ligne legale", legal.legalLine],
  ].filter(([, value]) => value);
  const slots = Array.isArray(availability.slots) ? availability.slots : [];

  if (!rows.length && !slots.length) return null;

  return (
    <section className="section section--alt" data-lpv-pattern-details>
      <div className="wrap">
        <SectionLabel num="LPV" title="Informations de publication" />
        <div className="legal-grid">
          {rows.map(([label, value]) => (
            <article className="legal-card" key={label}>
              <h3>{label}</h3>
              <p>{value}</p>
            </article>
          ))}
          {slots.map((slot) => (
            <article className="legal-card" key={slot.id || slot.label}>
              <h3>{slot.id}</h3>
              <p>
                {slot.label}
                {slot.time ? ` - ${slot.time}` : ""}
              </p>
            </article>
          ))}
        </div>
      </div>
    </section>
  );
}

window.PARAMEDICAL_INTERIM_DEFAULT_CONTENT = DEFAULT_CONTENT;
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
