// ============================================
// Admin & Preview Pages
// Hybrid-Auth: JS-Login-Form, Caddy-basicauth im Hintergrund
// ============================================

const ADMIN_USERS = ["alex", "joschi", "jonas"];
const ADMIN_STORAGE_KEY = "cine-admin-creds";

// ---------- Auth Helper ----------
function getStoredCreds() {
  try {
    const raw = sessionStorage.getItem(ADMIN_STORAGE_KEY);
    if (!raw) return null;
    const { user, basic } = JSON.parse(raw);
    if (!user || !basic) return null;
    return { user, basic };
  } catch (e) {
    return null;
  }
}

function setStoredCreds(user, basic) {
  sessionStorage.setItem(ADMIN_STORAGE_KEY, JSON.stringify({ user, basic }));
}

function clearStoredCreds() {
  sessionStorage.removeItem(ADMIN_STORAGE_KEY);
}

function buildBasic(user, password) {
  // btoa() wirft InvalidCharacterError bei Zeichen > 0xFF (z.B. Umlaute, Emojis).
  // Wir kodieren daher zuerst nach UTF-8 und mappen jedes Byte in den Latin-1-Bereich,
  // bevor wir base64-encoden. So funktioniert das auch mit beliebigen Passwoertern.
  const raw = user + ":" + password;
  const utf8 = unescape(encodeURIComponent(raw));
  return "Basic " + btoa(utf8);
}

// useAuth hook
function useAuth() {
  const [creds, setCreds] = useState(getStoredCreds());
  const isAuthed = !!creds;
  const user = creds?.user || null;

  const login = async (u, p) => {
    const basic = buildBasic(u, p);
    const res = await fetch("/admin-data/previews.json", {
      headers: { "Authorization": basic },
      cache: "no-store",
      credentials: "omit",
    });
    if (res.status === 200) {
      setStoredCreds(u, basic);
      setCreds({ user: u, basic });
      return { ok: true };
    }
    if (res.status === 401) return { ok: false, error: "credentials" };
    return { ok: false, error: "network" };
  };

  const logout = () => {
    clearStoredCreds();
    setCreds(null);
  };

  const authHeader = () => creds?.basic || null;

  return { user, isAuthed, login, logout, authHeader };
}

// Fetch wrapper with auth
async function fetchPreviews(authHeader) {
  if (!authHeader) throw new Error("no-auth");
  const res = await fetch("/admin-data/previews.json", {
    headers: { "Authorization": authHeader },
    cache: "no-store",
    credentials: "omit",
  });
  if (res.status === 401) throw new Error("auth");
  if (!res.ok) throw new Error("http-" + res.status);
  return res.json();
}

// ---------- LoginPage ----------
function LoginPage({ nextRoute, onNavigate }) {
  const { t } = useLang();
  const { isAuthed, login } = useAuth();
  const [user, setUser] = useState(ADMIN_USERS[0]);
  const [password, setPassword] = useState("");
  const [error, setError] = useState(null);
  const [submitting, setSubmitting] = useState(false);
  const pwRef = useRef(null);

  // Wenn bereits eingeloggt, direkt weiter
  useEffect(() => {
    if (isAuthed) onNavigate(nextRoute || { name: "admin" });
  }, [isAuthed]);

  useEffect(() => { pwRef.current?.focus(); }, []);

  const onSubmit = async (e) => {
    e.preventDefault();
    if (!password || submitting) return;
    setSubmitting(true);
    setError(null);
    const res = await login(user, password);
    setSubmitting(false);
    if (res.ok) {
      onNavigate(nextRoute || { name: "admin" });
    } else {
      setError(res.error === "credentials" ? t("login.error") : t("login.networkError"));
      setPassword("");
      pwRef.current?.focus();
    }
  };

  return (
    <section className="admin-auth-section">
      <div className="login-card">
        <div className="login-eyebrow">CINEPHILES</div>
        <h1 className="login-title">{t("login.title")}</h1>
        <div className="login-subtitle">{t("login.subtitle")}</div>

        <form onSubmit={onSubmit} className="login-form" autoComplete="on">
          <label className="login-field">
            <span className="login-label">{t("login.user")}</span>
            <select
              className="login-select"
              value={user}
              onChange={(e) => setUser(e.target.value)}
              autoComplete="username"
            >
              {ADMIN_USERS.map((u) => (
                <option key={u} value={u}>{u}</option>
              ))}
            </select>
          </label>

          <label className="login-field">
            <span className="login-label">{t("login.password")}</span>
            <input
              ref={pwRef}
              type="password"
              className="login-input"
              value={password}
              onChange={(e) => setPassword(e.target.value)}
              autoComplete="current-password"
              spellCheck="false"
              autoCapitalize="none"
              autoCorrect="off"
            />
          </label>

          {error && <div className="login-error" role="alert">{error}</div>}

          <button
            type="submit"
            className="btn-admin-primary"
            disabled={submitting || !password}
          >
            {submitting ? t("login.signingIn") : t("login.submit")}
          </button>
        </form>
      </div>
    </section>
  );
}

// ---------- AdminDashboard ----------
function AdminDashboard({ onNavigate }) {
  const { t } = useLang();
  const { user, isAuthed, logout, authHeader } = useAuth();
  const [previews, setPreviews] = useState(null);
  const [loadError, setLoadError] = useState(null);
  const [copiedSlug, setCopiedSlug] = useState(null);

  useEffect(() => {
    if (!isAuthed) {
      onNavigate({ name: "login" });
      return;
    }
    let alive = true;
    fetchPreviews(authHeader())
      .then((data) => { if (alive) setPreviews(data.previews || []); })
      .catch((err) => {
        if (!alive) return;
        if (err.message === "auth") {
          logout();
          onNavigate({ name: "login" });
        } else {
          setLoadError(err.message);
        }
      });
    return () => { alive = false; };
  }, [isAuthed]);

  const copyLink = async (slug) => {
    const url = window.location.origin + "/preview/" + slug;
    try {
      await navigator.clipboard.writeText(url);
      setCopiedSlug(slug);
      setTimeout(() => setCopiedSlug(null), 1800);
    } catch (e) {
      // Fallback: prompt
      window.prompt("Copy link:", url);
    }
  };

  if (!isAuthed) return null;

  return (
    <section className="admin-shell">
      <header className="admin-header">
        <div className="admin-header-left">
          <div className="eyebrow">{t("admin.title")}</div>
          <h1 className="admin-h1">{t("admin.subtitle")}</h1>
        </div>
        <div className="admin-header-right">
          <span className="admin-user-pill">{t("admin.loggedInAs", { user })}</span>
          <button
            type="button"
            className="btn-admin-ghost"
            onClick={() => { logout(); onNavigate({ name: "login" }); }}
          >
            {t("admin.logout")}
          </button>
        </div>
      </header>

      {previews === null && !loadError && (
        <div className="admin-loading">{t("admin.loading")}</div>
      )}

      {loadError && (
        <div className="admin-error">Error: {loadError}</div>
      )}

      {previews && previews.length === 0 && (
        <div className="admin-empty">{t("admin.empty")}</div>
      )}

      {previews && previews.length > 0 && (
        <ul className="preview-list">
          {previews.map((p) => (
            <li key={p.slug} className="preview-card">
              <div className="preview-card-body">
                <div className="preview-card-meta">
                  <span className="preview-version">{t("admin.version", { v: p.version })}</span>
                  <span className="preview-dot">·</span>
                  <span className="preview-date">{t("admin.added", { date: p.createdAt })}</span>
                </div>
                <h2 className="preview-card-title">{p.title}</h2>
                {p.directors && p.directors.length > 0 && (
                  <div className="preview-card-credits">
                    {t("admin.directedBy", { names: p.directors.join(", ") })}
                  </div>
                )}
                {p.notes && <p className="preview-card-notes">{p.notes}</p>}
              </div>
              <div className="preview-card-actions">
                <button
                  type="button"
                  className="btn-admin-primary"
                  onClick={() => onNavigate({ name: "preview", slug: p.slug })}
                >
                  {t("admin.open")}
                </button>
                <button
                  type="button"
                  className="btn-admin-ghost"
                  onClick={() => copyLink(p.slug)}
                >
                  {copiedSlug === p.slug ? t("admin.linkCopied") : t("admin.copyLink")}
                </button>
              </div>
            </li>
          ))}
        </ul>
      )}
    </section>
  );
}

// ---------- PreviewPage ----------
function PreviewPage({ slug, onNavigate }) {
  const { t } = useLang();
  const { isAuthed, authHeader, logout } = useAuth();
  const [preview, setPreview] = useState(undefined); // undefined=loading, null=notfound, obj=ok
  const [loadError, setLoadError] = useState(null);

  useEffect(() => {
    if (!isAuthed) {
      onNavigate({ name: "login", next: { name: "preview", slug } });
      return;
    }
    let alive = true;
    fetchPreviews(authHeader())
      .then((data) => {
        if (!alive) return;
        const p = (data.previews || []).find((x) => x.slug === slug);
        setPreview(p || null);
      })
      .catch((err) => {
        if (!alive) return;
        if (err.message === "auth") {
          onNavigate({ name: "login", next: { name: "preview", slug } });
        } else {
          setLoadError(err.message);
          setPreview(null);
        }
      });
    return () => { alive = false; };
  }, [isAuthed, slug]);

  if (!isAuthed) return null;

  return (
    <section className="preview-screen">
      <div className="preview-topbar">
        <button
          type="button"
          className="preview-back"
          onClick={() => onNavigate({ name: "admin" })}
          aria-label={t("preview.back")}
        >
          <svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true">
            <path d="M10 13L4 8L10 3" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
          <span>{t("preview.back")}</span>
        </button>
        {preview && (
          <div className="preview-topbar-title">
            <span className="preview-topbar-name">{preview.title}</span>
            <span className="preview-topbar-version">{preview.version}</span>
          </div>
        )}
        <div className="preview-topbar-right">
          <div className="preview-topbar-confidential">{t("preview.confidential")}</div>
          <button
            type="button"
            className="preview-logout"
            onClick={() => { logout(); onNavigate({ name: "login" }); }}
            aria-label={t("admin.logout")}
          >
            {t("admin.logout")}
          </button>
        </div>
      </div>

      <div className="preview-player-wrap">
        {preview === undefined && (
          <div className="preview-status">{t("preview.loading")}</div>
        )}
        {preview === null && !loadError && (
          <div className="preview-status">{t("preview.notFound")}</div>
        )}
        {loadError && (
          <div className="preview-status">Error: {loadError}</div>
        )}
        {preview && (
          <div className="preview-player">
            <iframe
              src={`https://player.vimeo.com/video/${preview.vimeoId}?h=${preview.vimeoHash}&badge=0&autopause=0&dnt=1&title=0&byline=0&portrait=0`}
              allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share"
              allowFullScreen
              referrerPolicy="strict-origin-when-cross-origin"
              title={preview.title + " " + preview.version}
              frameBorder="0"
            />
          </div>
        )}
      </div>
    </section>
  );
}

Object.assign(window, {
  useAuth,
  LoginPage,
  AdminDashboard,
  PreviewPage,
});
