const { useEffect, useMemo, useState } = React;

const API_BASE = "/api";

const monthLabels = [
  "Jan", "Fev", "Mar", "Avr", "Mai", "Juin",
  "Juil", "Aout", "Sep", "Oct", "Nov", "Dec"
];

function fetchJson(path) {
  return fetch(path).then(async (r) => {
    if (!r.ok) {
      throw new Error(`Erreur chargement ${path}`);
    }
    return r.json();
  });
}

function apiFetch(path, token, options = {}) {
  const headers = Object.assign(
    { "Content-Type": "application/json" },
    options.headers || {}
  );
  if (token) headers.Authorization = `Bearer ${token}`;
  return fetch(`${API_BASE}${path}`, { ...options, headers }).then(async (r) => {
    if (!r.ok) {
      const msg = await r.text();
      throw new Error(msg || "Erreur API");
    }
    return r.json();
  });
}

function formatMoney(n) {
  return new Intl.NumberFormat("fr-FR", {
    style: "currency",
    currency: "EUR",
    maximumFractionDigits: 0,
  }).format(n || 0);
}

function formatInt(n) {
  return new Intl.NumberFormat("fr-FR").format(n || 0);
}

function App() {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [token, setToken] = useState(localStorage.getItem("sf_token") || "");
  const [authUser, setAuthUser] = useState(null);

  const [centers, setCenters] = useState([]);
  const [kpis, setKpis] = useState([]);
  const [budgets, setBudgets] = useState([]);

  const [loginId, setLoginId] = useState("");
  const [loginPwd, setLoginPwd] = useState("");
  const [loginError, setLoginError] = useState("");
  const [demoRoles, setDemoRoles] = useState([]);
  const [demoUsers, setDemoUsers] = useState([]);
  const [demoRole, setDemoRole] = useState("");
  const [demoUserId, setDemoUserId] = useState("");
  const [demoError, setDemoError] = useState("");

  const [selectedYear, setSelectedYear] = useState(2025);
  const [selectedCenter, setSelectedCenter] = useState("ALL");
  const [showPwdModal, setShowPwdModal] = useState(false);
  const [pwdOld, setPwdOld] = useState("");
  const [pwdNew, setPwdNew] = useState("");
  const [pwdError, setPwdError] = useState("");

  useEffect(() => {
    if (!token) {
      setLoading(false);
      return;
    }
    apiFetch("/me", token)
      .then((u) => {
        setAuthUser(u);
        if (u.center_id && u.center_id !== "*") {
          setSelectedCenter(u.center_id);
        }
        if (u.must_change_password) {
          setShowPwdModal(true);
        }
      })
      .catch(() => {
        setToken("");
        localStorage.removeItem("sf_token");
      })
      .finally(() => setLoading(false));
  }, [token]);

  useEffect(() => {
    Promise.all([fetchJson("/config/roles.json"), fetchJson("/config/users.json")])
      .then(([rolesJson, usersJson]) => {
        setDemoRoles(rolesJson);
        setDemoUsers(usersJson);

        const firstRole = rolesJson.find((r) =>
          usersJson.some((u) => u.role_id === r.role_id)
        );
        const fallbackUser = usersJson[0];
        if (firstRole) {
          setDemoRole(firstRole.role_id);
          const firstUserForRole = usersJson.find((u) => u.role_id === firstRole.role_id);
          setDemoUserId(firstUserForRole ? firstUserForRole.user_id : "");
        } else if (fallbackUser) {
          setDemoRole(fallbackUser.role_id);
          setDemoUserId(fallbackUser.user_id);
        }
        setDemoError("");
      })
      .catch(() => {
        setDemoError("Mode demo indisponible (configuration non chargee)");
      });
  }, []);

  useEffect(() => {
    if (!token) return;
    apiFetch("/centers", token)
      .then(setCenters)
      .catch((e) => setError(e.message || "Erreur chargement centres"));
  }, [token]);

  useEffect(() => {
    if (!token) return;
    setLoading(true);
    Promise.all([
      apiFetch(`/kpi?year=${selectedYear}&center=${selectedCenter}`, token),
      apiFetch(`/budgets?year=${selectedYear}&center=${selectedCenter}`, token),
    ])
      .then(([k, b]) => {
        const parsedKpis = k.map((r) => ({
          ...r,
          revenue: Number(r.revenue),
          expenses: Number(r.expenses),
          margin: Number(r.margin),
          jobs_leak_detection: Number(r.jobs_leak_detection),
          jobs_networks: Number(r.jobs_networks),
          incident_rate: Number(r.incident_rate),
          sla_compliance: Number(r.sla_compliance),
          year: Number(r.date.slice(0, 4)),
          month: Number(r.date.slice(5, 7)),
        }));
        setKpis(parsedKpis);
        setBudgets(
          b.map((r) => ({
            ...r,
            year: Number(r.year),
            budget_revenue: Number(r.budget_revenue),
            budget_expenses: Number(r.budget_expenses),
            target_margin_pct: Number(r.target_margin_pct),
          }))
        );
        setError("");
      })
      .catch((e) => setError(e.message || "Erreur chargement donnees"))
      .finally(() => setLoading(false));
  }, [token, selectedYear, selectedCenter]);

  const years = useMemo(() => {
    return [2023, 2024, 2025];
  }, []);

  const demoRoleOptions = useMemo(() => {
    if (!demoRoles.length || !demoUsers.length) return [];
    return demoRoles.filter((r) => demoUsers.some((u) => u.role_id === r.role_id));
  }, [demoRoles, demoUsers]);

  const demoUsersForRole = useMemo(() => {
    if (!demoUsers.length) return [];
    return demoUsers
      .filter((u) => !demoRole || u.role_id === demoRole)
      .sort((a, b) => a.user_id.localeCompare(b.user_id));
  }, [demoUsers, demoRole]);

  useEffect(() => {
    if (!demoUsersForRole.length) {
      setDemoUserId("");
      return;
    }
    if (!demoUsersForRole.some((u) => u.user_id === demoUserId)) {
      setDemoUserId(demoUsersForRole[0].user_id);
    }
  }, [demoUsersForRole, demoUserId]);

  const monthly = useMemo(() => {
    const map = new Map();
    for (let m = 1; m <= 12; m++) {
      map.set(m, {
        month: m,
        revenue: 0,
        expenses: 0,
        margin: 0,
        jobs: 0,
        sla_sum: 0,
        sla_count: 0,
      });
    }

    kpis.forEach((k) => {
      if (k.year !== selectedYear) return;
      const bucket = map.get(k.month);
      bucket.revenue += k.revenue;
      bucket.expenses += k.expenses;
      bucket.margin += k.margin;
      bucket.jobs += k.jobs_leak_detection + k.jobs_networks;
      bucket.sla_sum += k.sla_compliance;
      bucket.sla_count += 1;
    });

    return Array.from(map.values()).map((b) => ({
      ...b,
      sla: b.sla_count ? b.sla_sum / b.sla_count : 0,
    }));
  }, [kpis, selectedYear]);

  const totals = useMemo(() => {
    const t = monthly.reduce(
      (acc, m) => {
        acc.revenue += m.revenue;
        acc.expenses += m.expenses;
        acc.margin += m.margin;
        acc.jobs += m.jobs;
        acc.sla_sum += m.sla;
        acc.sla_count += 1;
        return acc;
      },
      { revenue: 0, expenses: 0, margin: 0, jobs: 0, sla_sum: 0, sla_count: 0 }
    );
    return {
      ...t,
      margin_pct: t.revenue ? (t.margin / t.revenue) * 100 : 0,
      sla: t.sla_count ? t.sla_sum / t.sla_count : 0,
    };
  }, [monthly]);

  const budget = useMemo(() => {
    if (!budgets.length) return { revenue: 0, expenses: 0, target_margin_pct: 0 };
    const total = budgets.reduce(
      (acc, b) => {
        acc.revenue += b.budget_revenue;
        acc.expenses += b.budget_expenses;
        acc.target_margin_pct += b.target_margin_pct;
        return acc;
      },
      { revenue: 0, expenses: 0, target_margin_pct: 0 }
    );
    return {
      revenue: total.revenue,
      expenses: total.expenses,
      target_margin_pct: total.target_margin_pct / budgets.length,
    };
  }, [budgets]);

  const alerts = useMemo(() => {
    const lowMarginMonths = monthly.filter((m) => m.margin < 0).length;
    const lowSlaMonths = monthly.filter((m) => m.sla < 90).length;
    return { lowMarginMonths, lowSlaMonths };
  }, [monthly]);

  const maxMargin = useMemo(() => {
    return Math.max(...monthly.map((m) => Math.abs(m.margin)), 1);
  }, [monthly]);

  const loginWithCredentials = async (userId, password) => {
    try {
      const res = await apiFetch("/auth/login", "", {
        method: "POST",
        body: JSON.stringify({ user_id: userId, password }),
      });
      localStorage.setItem("sf_token", res.token);
      setToken(res.token);
      setAuthUser(res.user);
      setLoginError("");
      if (res.user.center_id && res.user.center_id !== "*") {
        setSelectedCenter(res.user.center_id);
      } else {
        setSelectedCenter("ALL");
      }
      if (res.user.must_change_password) {
        setShowPwdModal(true);
      }
    } catch (e) {
      setLoginError("Identifiants invalides");
    }
  };

  const handleLogin = async (e) => {
    e.preventDefault();
    await loginWithCredentials(loginId, loginPwd);
  };

  const handleDemoLogin = async () => {
    const selectedDemoUser = demoUsers.find((u) => u.user_id === demoUserId);
    if (!selectedDemoUser) {
      setLoginError("Profil demo introuvable");
      return;
    }
    setLoginId(selectedDemoUser.user_id);
    setLoginPwd(selectedDemoUser.password);
    await loginWithCredentials(selectedDemoUser.user_id, selectedDemoUser.password);
  };

  const handleChangePassword = async (e) => {
    e.preventDefault();
    setPwdError("");
    try {
      await apiFetch("/auth/change-password", token, {
        method: "POST",
        body: JSON.stringify({ old_password: pwdOld, new_password: pwdNew }),
      });
      setShowPwdModal(false);
      setPwdOld("");
      setPwdNew("");
    } catch (e) {
      setPwdError("Impossible de changer le mot de passe");
    }
  };

  const handleLogout = () => {
    setAuthUser(null);
    setToken("");
    localStorage.removeItem("sf_token");
  };

  if (loading && !authUser) {
    return (
      <div className="splash">
        <div className="loader">Chargement...</div>
      </div>
    );
  }

  if (!authUser) {
    return (
      <div className="splash">
        <div className="login-card">
          <div className="logo">Suivi financier</div>
          <p className="subtitle">
            Application de pilotage pour 10 centres de profits
          </p>
          <form onSubmit={handleLogin} className="login-form">
            <label>
              Identifiant
              <input
                value={loginId}
                onChange={(e) => setLoginId(e.target.value)}
                placeholder="ex: admin"
                required
              />
            </label>
            <label>
              Mot de passe
              <input
                type="password"
                value={loginPwd}
                onChange={(e) => setLoginPwd(e.target.value)}
                placeholder="ex: Admin#2026"
                required
              />
            </label>
            {loginError && <div className="error-msg">{loginError}</div>}
            <button type="submit">Connexion</button>
          </form>
          <div className="demo-switcher">
            <div className="demo-title">Mode demo: test des roles</div>
            <div className="demo-grid">
              <label>
                Role
                <select
                  value={demoRole}
                  onChange={(e) => setDemoRole(e.target.value)}
                  disabled={!demoRoleOptions.length}
                >
                  {demoRoleOptions.map((r) => (
                    <option key={r.role_id} value={r.role_id}>
                      {r.label} ({r.role_id})
                    </option>
                  ))}
                </select>
              </label>
              <label>
                Profil
                <select
                  value={demoUserId}
                  onChange={(e) => setDemoUserId(e.target.value)}
                  disabled={!demoUsersForRole.length}
                >
                  {demoUsersForRole.map((u) => (
                    <option key={u.user_id} value={u.user_id}>
                      {u.user_id}
                      {u.center_id !== "*" ? ` - ${u.center_id}` : ""}
                    </option>
                  ))}
                </select>
              </label>
            </div>
            <button
              type="button"
              className="ghost demo-login-btn"
              onClick={handleDemoLogin}
              disabled={!demoUserId}
            >
              Ouvrir avec ce profil
            </button>
            {demoError && <div className="error-msg">{demoError}</div>}
          </div>
          <div className="hint">Version securisee avec mot de passe modifiable.</div>
        </div>
      </div>
    );
  }

  return (
    <div className="app">
      <header className="topbar">
        <div>
          <div className="title">Suivi financier</div>
          <div className="subtitle">
            Centre de profits | Detection fuites & reseaux
          </div>
        </div>
        <div className="user-chip">
          <div className="user-name">{authUser.user_id}</div>
          <div className="user-role">{authUser.role_id}</div>
          <div className="user-actions">
            <button className="ghost" onClick={() => setShowPwdModal(true)}>
              Changer MDP
            </button>
            <button className="ghost" onClick={handleLogout}>
              Deconnexion
            </button>
          </div>
        </div>
      </header>

      <section className="filters">
        <div className="pill">
          <span>Annee</span>
          <select
            value={selectedYear}
            onChange={(e) => setSelectedYear(Number(e.target.value))}
          >
            {years.map((y) => (
              <option key={y} value={y}>
                {y}
              </option>
            ))}
          </select>
        </div>
        <div className="pill">
          <span>Centre</span>
          <select
            value={selectedCenter}
            onChange={(e) => setSelectedCenter(e.target.value)}
            disabled={authUser.center_id !== "*"}
          >
            <option value="ALL">Tous les centres</option>
            {centers.map((c) => (
              <option key={c.center_id} value={c.center_id}>
                {c.name}
              </option>
            ))}
          </select>
        </div>
        <div className="pill">
          <span>Periode</span>
          <strong>{selectedYear}-01 a {selectedYear}-12</strong>
        </div>
      </section>

      {error && (
        <section className="panel">
          <div className="error-msg">{error}</div>
        </section>
      )}

      <section className="grid">
        <div className="card">
          <div className="label">Chiffre d'affaires</div>
          <div className="value">{formatMoney(totals.revenue)}</div>
          <div className="delta">Budget: {formatMoney(budget.revenue)}</div>
        </div>
        <div className="card">
          <div className="label">Charges</div>
          <div className="value">{formatMoney(totals.expenses)}</div>
          <div className="delta">Budget: {formatMoney(budget.expenses)}</div>
        </div>
        <div className="card">
          <div className="label">Marge</div>
          <div className="value">{formatMoney(totals.margin)}</div>
          <div className="delta">
            {totals.margin_pct.toFixed(1)}% | Cible {budget.target_margin_pct.toFixed(1)}%
          </div>
        </div>
        <div className="card">
          <div className="label">Interventions</div>
          <div className="value">{formatInt(totals.jobs)}</div>
          <div className="delta">Fuites + Reseaux</div>
        </div>
        <div className="card">
          <div className="label">SLA moyen</div>
          <div className="value">{totals.sla.toFixed(1)}%</div>
          <div className="delta">Seuil interne: 92%</div>
        </div>
        <div className="card alert">
          <div className="label">Alertes</div>
          <div className="value">{alerts.lowMarginMonths + alerts.lowSlaMonths}</div>
          <div className="delta">
            {alerts.lowMarginMonths} mois marge negative, {alerts.lowSlaMonths} mois SLA &lt; 90%
          </div>
        </div>
      </section>

      <section className="panel">
        <div className="panel-title">Marge mensuelle</div>
        <div className="chart">
          {monthly.map((m, idx) => {
            const height = Math.round((Math.abs(m.margin) / maxMargin) * 100);
            const negative = m.margin < 0;
            return (
              <div key={m.month} className="bar-wrap">
                <div
                  className={`bar ${negative ? "neg" : "pos"}`}
                  style={{ height: `${height}%` }}
                  title={`${monthLabels[idx]}: ${formatMoney(m.margin)}`}
                ></div>
                <div className="bar-label">{monthLabels[idx]}</div>
              </div>
            );
          })}
        </div>
      </section>

      <section className="panel table">
        <div className="panel-title">Detail mensuel</div>
        <div className="table-grid">
          <div className="thead">
            <div>Mois</div>
            <div>CA</div>
            <div>Charges</div>
            <div>Marge</div>
            <div>Interventions</div>
            <div>SLA</div>
          </div>
          {monthly.map((m, idx) => (
            <div className="trow" key={`row-${m.month}`}>
              <div>{monthLabels[idx]}</div>
              <div>{formatMoney(m.revenue)}</div>
              <div>{formatMoney(m.expenses)}</div>
              <div className={m.margin < 0 ? "neg" : "pos"}>
                {formatMoney(m.margin)}
              </div>
              <div>{formatInt(m.jobs)}</div>
              <div>{m.sla.toFixed(1)}%</div>
            </div>
          ))}
        </div>
      </section>

      {showPwdModal && (
        <div className="modal-backdrop">
          <div className="modal">
            <div className="panel-title">Changer le mot de passe</div>
            <form onSubmit={handleChangePassword} className="login-form">
              <label>
                Ancien mot de passe
                <input
                  type="password"
                  value={pwdOld}
                  onChange={(e) => setPwdOld(e.target.value)}
                  required
                />
              </label>
              <label>
                Nouveau mot de passe
                <input
                  type="password"
                  value={pwdNew}
                  onChange={(e) => setPwdNew(e.target.value)}
                  required
                />
              </label>
              {pwdError && <div className="error-msg">{pwdError}</div>}
              <div className="modal-actions">
                <button type="submit">Mettre a jour</button>
                <button
                  type="button"
                  className="ghost"
                  onClick={() => setShowPwdModal(false)}
                >
                  Annuler
                </button>
              </div>
            </form>
          </div>
        </div>
      )}
    </div>
  );
}

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