// app.jsx — Racine RAYCAST. Auth Supabase + routes + sauvegarde cloud.

const { useState, useEffect, useMemo, useCallback } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#1a6fc4",
  "density": "regular",
  "ttcStyle": "gradient",
  "previewWidth": "balanced",
  "showHints": true
}/*EDITMODE-END*/;

// ═══════════════════════════════════════════════════════════════════
// État initial : valeurs vides par défaut. Le numéro de soumission
// est null tant que la soumission n'est pas sauvegardée/envoyée.
// ═══════════════════════════════════════════════════════════════════
function buildInitialState() {
  const now = new Date();
  return {
    quote_id: null,               // ← Supabase : null = brouillon, "2026-0001" sinon
    created_at: now.toISOString().slice(0, 10),
    project_type: "solaire_batterie",
    building_type: "residentiel_unifam",
    client: {
      client_id: null,            // ← Supabase : lien vers clients.id
      name: "",
      phone: "",
      email: "",
      address_civic: "",
      address_apt: "",
      address_street: "",
      address_city: "",
      address_postal: "",
      address_province: "QC",
      source: "Référence client",
      region_id: "mascouche",
      orientation: "S",
      hq_tariff: "FlexD",
      bill_input_mode: "dollars",
      annual_hq_bill: 2840,
      annual_hq_kwh: 36500,
      ev_km_per_year: 18000,
      ev_kwh_per_100km: 18.5,
      financing_plan_id: "240m"
    },
    solar: {
      kw: 10, panel_watts: 500, roof_type: "asphalte", slope: 1, floors: 2,
      with_battery: true, battery_brand: "tesla", battery_preset_id: "tesla-1pw3",
      battery_kwh: 13.5, with_dim: true, backup_mode: "partial",
      service_amperage: 200, with_v2x: false,
      cost_solar: 0, cost_inverter: 0, cost_batteries: 0, cost_install: 0
    },
    ve: {
      bornes_selected: [{ key: "tesla_wc3_univ", qty: 1 }],
      quantity: 1, scenario_post_2018: true,
      cable_length_pi: 50, dcc_option: "aucun",
      manual_borne_price: 0, manual_borne_rve: 0
    },
    options: []
  };
}

// ═══════════════════════════════════════════════════════════════════
// Sidebar — navigation + identité utilisateur
// ═══════════════════════════════════════════════════════════════════
const Sidebar = ({ view, setView, profile, isAdmin, onSignOut }) => (
  <aside className="sidebar">
    <div className="sidebar-logo">
      <RaycomLogo size={32}/>
    </div>
    <nav>
      <div className={`nav-item ${view === "repository" ? "active" : ""}`} onClick={() => setView("repository")}>
        <Icon name="folder" size={14}/>
        Répertoire
      </div>
      <div className={`nav-item ${view === "configurator" ? "active" : ""}`} onClick={() => setView("configurator")}>
        <Icon name="plus" size={14}/>
        Nouvelle soumission
      </div>
      <div className="nav-item disabled">
        <Icon name="package" size={14}/>
        Catalogue
        <span className="badge">S4</span>
      </div>
      <div className="nav-item disabled">
        <Icon name="users" size={14}/>
        Clients
        <span className="badge">V1.1</span>
      </div>
      {isAdmin && (
        <div className="nav-item disabled">
          <Icon name="settings" size={14}/>
          Paramètres
          <span className="badge">S5</span>
        </div>
      )}
    </nav>

    {profile && (
      <div className="sidebar-user">
        <div className="user-avatar" style={{ background: avatarBg(profile.name) }}>
          {(profile.initials || (profile.name || "?").slice(0, 2)).toUpperCase()}
        </div>
        <div className="user-info">
          <div className="user-name">{profile.name}</div>
          <div className="user-role">{profile.role === "admin" ? "Administrateur" : "Vendeur"}</div>
        </div>
        <button className="user-signout" onClick={onSignOut} title="Se déconnecter">
          <Icon name="log-out" size={13}/>
        </button>
      </div>
    )}

    <div className="sidebar-foot">
      <em>« Prenez le contrôle de votre énergie. »</em>
      RBQ 5590-9402-01 · CMEQ<br/>
      Mascouche (QC)
    </div>
  </aside>
);

function avatarBg(name) {
  if (!name) return "#94a3b8";
  let h = 0;
  for (let i = 0; i < name.length; i++) h = name.charCodeAt(i) + ((h << 5) - h);
  return `hsl(${Math.abs(h) % 360}, 45%, 50%)`;
}

// ═══════════════════════════════════════════════════════════════════
// Toolbar — header de l'écran configurateur avec Save/Envoyer
// ═══════════════════════════════════════════════════════════════════
const Toolbar = ({ quoteId, status, dirty, busy, viewMode, setViewMode, onSave, onSend, onBack }) => {
  const statusLabel = ({
    brouillon: { label: "Brouillon", color: "#64748b", bg: "#f1f5f9" },
    envoye:    { label: "Envoyée",   color: "#1e40af", bg: "#dbeafe" },
    accepte:   { label: "Acceptée",  color: "#166534", bg: "#dcfce7" },
    refuse:    { label: "Refusée",   color: "#991b1b", bg: "#fee2e2" },
    archive:   { label: "Archivée",  color: "#6b21a8", bg: "#e9d5ff" }
  })[status] || { label: "Brouillon", color: "#64748b", bg: "#f1f5f9" };

  return (
    <div className="toolbar">
      <button className="btn-ghost" onClick={onBack} title="Retour au répertoire" style={{ marginRight: 8 }}>
        <Icon name="arrow-left" size={14}/>
      </button>
      <div style={{ display: "flex", flexDirection: "column", lineHeight: 1.15 }}>
        <span className="caption">Soumission {dirty && <span style={{ color: "#d97706" }}>· modifiée</span>}</span>
        <span className="quote-no">
          {quoteId || <span style={{ fontStyle: "italic", opacity: 0.7 }}>brouillon non sauvegardé</span>}
          <span style={{
            marginLeft: 10, padding: "2px 8px", borderRadius: 4,
            fontSize: 10.5, fontWeight: 700, letterSpacing: "0.02em",
            background: statusLabel.bg, color: statusLabel.color,
            verticalAlign: "middle"
          }}>{statusLabel.label}</span>
        </span>
      </div>
      <div className="spacer"/>
      <SegmentedToggle
        value={viewMode}
        options={[
          { value: "internal", label: "Vue interne", icon: "eye" },
          { value: "client", label: "Vue client", icon: "eye-off" }
        ]}
        onChange={setViewMode}
        accent={true}
      />
      <button className="btn-ghost" onClick={onSave} disabled={busy} title="Sauvegarder (brouillon)">
        <Icon name="save" size={13}/>{busy ? "…" : "Sauvegarder"}
      </button>
      {status === "brouillon" ? (
        <button className="btn-primary" onClick={onSend} disabled={busy} title="Marquer comme envoyée au client">
          <Icon name="send" size={13}/>Envoyer au client
        </button>
      ) : (
        <button className="btn-primary" disabled title="PDF — à venir">
          <Icon name="file-text" size={13}/>Générer PDF
        </button>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════
// App — racine : auth gate, routes, save logic
// ═══════════════════════════════════════════════════════════════════
const App = () => {
  const { session, user, profile, isAdmin, loading: authLoading, signIn, signOut } = useAuth();
  const [view, setView] = useState("repository");                 // "repository" | "configurator"
  const [state, setState] = useState(buildInitialState);
  const [submissionId, setSubmissionId] = useState(null);          // null = brouillon non sauvegardé
  const [submissionStatus, setSubmissionStatus] = useState("brouillon");
  const [dirty, setDirty] = useState(false);
  const [busy, setBusy] = useState(false);
  const [viewMode, setViewMode] = useState("internal");
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // ───── Apply tweaks (accent, density, preview width) ─────
  useEffect(() => {
    const root = document.documentElement;
    root.style.setProperty("--raycom-accent", t.accent);
    const hex = t.accent.replace("#", "");
    const r = parseInt(hex.slice(0,2),16), g = parseInt(hex.slice(2,4),16), b = parseInt(hex.slice(4,6),16);
    root.style.setProperty("--raycom-accent-dim", `rgba(${r},${g},${b},0.08)`);
    root.style.setProperty("--raycom-accent-tint", `rgba(${r},${g},${b},0.16)`);
    root.style.setProperty("--raycom-accent-dark",  `rgb(${Math.round(r*0.55)},${Math.round(g*0.55)},${Math.round(b*0.65)})`);
    root.style.setProperty("--raycom-accent-light", `rgb(${Math.min(255,Math.round(r+50))},${Math.min(255,Math.round(g+50))},${Math.min(255,Math.round(b+50))})`);
  }, [t.accent]);

  useEffect(() => {
    const root = document.documentElement;
    if (t.density === "compact") root.style.fontSize = "13px";
    else if (t.density === "comfy") root.style.fontSize = "15px";
    else root.style.fontSize = "14px";
  }, [t.density]);

  // ───── Marquer "dirty" sur toute modification du state ─────
  const setStateTracked = useCallback((next) => {
    setDirty(true);
    setState(next);
  }, []);

  const calc = useMemo(() => window.RAYCAST_CALC.fullCalc(state), [state]);

  // ───── Actions : Nouvelle soumission ─────
  const handleNew = useCallback(() => {
    setState(buildInitialState());
    setSubmissionId(null);
    setSubmissionStatus("brouillon");
    setDirty(false);
    setView("configurator");
  }, []);

  // ───── Actions : Ouvrir une soumission existante ─────
  const handleOpen = useCallback(async (id) => {
    setBusy(true);
    try {
      const row = await window.RaycastDB.getSubmission(id);
      if (!row) throw new Error("Soumission introuvable");
      const loaded = { ...row.data, quote_id: row.number };
      // S'assurer que client.client_id est rempli
      if (loaded.client && row.client_id) loaded.client.client_id = row.client_id;
      setState(loaded);
      setSubmissionId(row.id);
      setSubmissionStatus(row.status);
      setDirty(false);
      setView("configurator");
    } catch (e) {
      alert("Erreur d'ouverture : " + (e.message || e));
    } finally {
      setBusy(false);
    }
  }, []);

  // ───── Actions : Sauvegarder (brouillon ou maj) ─────
  const persist = useCallback(async ({ send = false } = {}) => {
    if (!user) return;
    setBusy(true);
    try {
      // 1) Upsert client (crée ou met à jour la fiche du répertoire)
      const clientId = await window.RaycastDB.upsertClientFromState(state.client, user.id);
      const stateWithClient = { ...state, client: { ...state.client, client_id: clientId } };

      let saved;
      if (!submissionId) {
        // Création initiale — un numéro est attribué automatiquement par createSubmission
        saved = await window.RaycastDB.createSubmission({
          state: stateWithClient, calc, userId: user.id, clientId
        });
      }
      // Maj (le numéro est déjà attribué dès la création — plus besoin de l'assigner ici)
      const targetId = saved ? saved.id : submissionId;
      const currentNumber = saved ? saved.number : state.quote_id;
      const finalRow = await window.RaycastDB.saveSubmission({
        id: targetId,
        state: stateWithClient,
        calc,
        userId: user.id,
        clientId,
        currentNumber
      });

      // Mise à jour du statut si envoi
      let finalStatus = submissionStatus;
      if (send && finalRow.status === "brouillon") {
        const upd = await window.RaycastDB.setSubmissionStatus(targetId, "envoye");
        finalStatus = upd.status;
      } else {
        finalStatus = finalRow.status;
      }

      setSubmissionId(targetId);
      setSubmissionStatus(finalStatus);
      setState({ ...stateWithClient, quote_id: finalRow.number });
      setDirty(false);
    } catch (e) {
      console.error(e);
      alert("Sauvegarde échouée : " + (e.message || e));
    } finally {
      setBusy(false);
    }
  }, [user, state, calc, submissionId, submissionStatus]);

  const handleSave = useCallback(() => persist({ send: false }), [persist]);
  const handleSend = useCallback(() => {
    if (!confirm("Marquer cette soumission comme « envoyée » au client ?\n\nLe statut passera de brouillon à envoyée et tu ne pourras plus la modifier librement.")) return;
    persist({ send: true });
  }, [persist]);

  // ───── Charger un client depuis le répertoire ─────
  const handlePickClient = useCallback((c) => {
    setStateTracked({
      ...state,
      client: {
        ...state.client,
        client_id:        c.id,
        name:             c.name || "",
        phone:            c.phone || "",
        email:            c.email || "",
        address_civic:    c.address_civic || "",
        address_apt:      c.address_apt || "",
        address_street:   c.address_street || "",
        address_city:     c.address_city || "",
        address_postal:   c.address_postal || "",
        address_province: c.address_province || "QC",
        source:           c.source || state.client.source,
        region_id:        c.region_id || state.client.region_id
      }
    });
  }, [state, setStateTracked]);

  // Exposer le handler pour que le Configurator y accède sans prop drilling
  useEffect(() => {
    window.RAYCAST_PICK_CLIENT = handlePickClient;
    return () => { delete window.RAYCAST_PICK_CLIENT; };
  }, [handlePickClient]);

  // ───── Layout ─────
  const previewGrid = t.previewWidth === "wide"
    ? "minmax(380px, 1fr) minmax(520px, 1.4fr) 320px"
    : t.previewWidth === "compact"
      ? "minmax(440px, 1.2fr) minmax(380px, 1fr) 320px"
      : "minmax(420px, 1fr) minmax(440px, 1.1fr) 320px";

  // ─── 1) Loading auth ───
  if (authLoading) return <FullscreenLoader/>;
  // ─── 2) Non connecté ───
  if (!session) return <LoginScreen onSignIn={signIn}/>;

  // ─── 3) App ───
  return (
    <div className="app">
      <Sidebar
        view={view} setView={setView}
        profile={profile} isAdmin={isAdmin}
        onSignOut={signOut}
      />
      <div>
        {view === "repository" ? (
          <Repository
            profile={profile}
            isAdmin={isAdmin}
            onOpen={handleOpen}
            onNew={handleNew}
          />
        ) : (
          <>
            <Toolbar
              quoteId={state.quote_id}
              status={submissionStatus}
              dirty={dirty}
              busy={busy}
              viewMode={viewMode}
              setViewMode={setViewMode}
              onSave={handleSave}
              onSend={handleSend}
              onBack={() => setView("repository")}
            />
            <div className="main" style={{ gridTemplateColumns: previewGrid }}>
              <div className="col-config">
                <Configurator state={state} setState={setStateTracked} calc={calc} viewMode={viewMode}/>
              </div>
              <div className="col-preview">
                <QuotePreview state={state} calc={calc} viewMode={viewMode}/>
              </div>
              <div className="col-right">
                <Dashboard state={state} calc={calc} viewMode={viewMode}/>
                <PriceSummary state={state} calc={calc} viewMode={viewMode}/>
              </div>
            </div>
          </>
        )}
      </div>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Identité"/>
        <TweakColor
          label="Accent"
          value={t.accent}
          options={["#1a6fc4", "#0d4a8a", "#0ea5e9", "#1f8a5b", "#7c3aed", "#dc2626"]}
          onChange={(v) => setTweak("accent", v)}
        />
        <TweakSection label="Mise en page"/>
        <TweakRadio
          label="Densité"
          value={t.density}
          options={["compact", "regular", "comfy"]}
          onChange={(v) => setTweak("density", v)}
        />
        <TweakSelect
          label="Largeur preview"
          value={t.previewWidth}
          options={["compact", "balanced", "wide"]}
          onChange={(v) => setTweak("previewWidth", v)}
        />
        <TweakSection label="Outils"/>
        <TweakButton onClick={() => window.open("backtest.html", "_blank")}>
          ▶ Backtest 1000 soumissions
        </TweakButton>
      </TweaksPanel>
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════
// FullscreenLoader — spinner pendant l'init auth
// ═══════════════════════════════════════════════════════════════════
const FullscreenLoader = () => (
  <div style={{
    position: "fixed", inset: 0,
    background: "radial-gradient(ellipse at top, #0d2540 0%, #050a14 60%)",
    display: "flex", alignItems: "center", justifyContent: "center",
    color: "#94a3b8", fontFamily: "'Inter', system-ui, sans-serif", fontSize: 13
  }}>
    <div style={{ textAlign: "center" }}>
      <div style={{
        width: 32, height: 32, margin: "0 auto 14px",
        border: "3px solid rgba(255,255,255,0.1)",
        borderTopColor: "#1a6fc4", borderRadius: "50%",
        animation: "raycast-spin 0.8s linear infinite"
      }}/>
      <div>Chargement…</div>
      <style>{`@keyframes raycast-spin { to { transform: rotate(360deg); } }`}</style>
    </div>
  </div>
);

ReactDOM.createRoot(document.getElementById("root")).render(<App/>);
