/* global React, ReactDOM */
const { useState, useEffect, useCallback } = React;

const CFG = window.SHIFA_CONFIG || {};
const API_BASE = CFG.apiBase || "";
const REGION = CFG.region || "ap-south-1";
const COGNITO = CFG.cognito || {};
const COGNITO_URL = `https://cognito-idp.${REGION}.amazonaws.com/`;
const TOKEN_KEY = "shifa_staff_token";

// ---------- Cognito (no SDK — direct JSON API over fetch) ----------
async function cognitoCall(target, body) {
  const res = await fetch(COGNITO_URL, {
    method: "POST",
    headers: {
      "Content-Type": "application/x-amz-json-1.1",
      "X-Amz-Target": `AWSCognitoIdentityProviderService.${target}`,
    },
    body: JSON.stringify(body),
  });
  const data = await res.json().catch(() => ({}));
  if (!res.ok) {
    throw new Error(data.message || data.__type || "Authentication failed");
  }
  return data;
}

async function signIn(email, password) {
  return cognitoCall("InitiateAuth", {
    AuthFlow: "USER_PASSWORD_AUTH",
    ClientId: COGNITO.clientId,
    AuthParameters: { USERNAME: email, PASSWORD: password },
  });
}

async function respondNewPassword(email, newPassword, session) {
  return cognitoCall("RespondToAuthChallenge", {
    ChallengeName: "NEW_PASSWORD_REQUIRED",
    ClientId: COGNITO.clientId,
    Session: session,
    ChallengeResponses: { USERNAME: email, NEW_PASSWORD: newPassword },
  });
}

// ---------- API ----------
async function api(path, { method = "GET", token } = {}) {
  const res = await fetch(`${API_BASE}${path}`, {
    method,
    headers: token ? { Authorization: `Bearer ${token}` } : {},
  });
  if (res.status === 401 || res.status === 403) {
    const e = new Error("Session expired. Please sign in again.");
    e.code = "AUTH";
    throw e;
  }
  const data = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(data.error || "Request failed");
  return data;
}

// ---------- Login screen ----------
function Login({ onToken }) {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [newPassword, setNewPassword] = useState("");
  const [session, setSession] = useState(null); // set when NEW_PASSWORD_REQUIRED
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");

  const configured = COGNITO.clientId && API_BASE;

  const submit = async (e) => {
    e.preventDefault();
    setErr(""); setBusy(true);
    try {
      let result;
      if (session) {
        result = await respondNewPassword(email, newPassword, session);
      } else {
        result = await signIn(email, password);
      }
      if (result.ChallengeName === "NEW_PASSWORD_REQUIRED") {
        setSession(result.Session);
        setBusy(false);
        return;
      }
      const token = result.AuthenticationResult && result.AuthenticationResult.IdToken;
      if (!token) throw new Error("No token returned");
      localStorage.setItem(TOKEN_KEY, token);
      onToken(token);
    } catch (e2) {
      setErr(e2.message);
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="login">
      <h2>Staff sign in</h2>
      <p>Shifa Dental appointment dashboard</p>
      {!configured && <div className="err">Backend not configured yet. Fill in <b>config.js</b> with your API + Cognito values.</div>}
      <form onSubmit={submit}>
        <label>Email</label>
        <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required autoFocus placeholder="staff@shifadental.in" />
        {!session ? (
          <>
            <label>Password</label>
            <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} required />
          </>
        ) : (
          <>
            <label>Set a new password</label>
            <input type="password" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} required placeholder="First-time login — choose a password" />
          </>
        )}
        {err && <div className="err">{err}</div>}
        <button type="submit" className="btn btn-primary" style={{ width: "100%", marginTop: 18 }} disabled={busy || !configured}>
          {busy ? "Please wait…" : session ? "Set password & continue" : "Sign in"}
        </button>
      </form>
    </div>
  );
}

// ---------- Appointment card ----------
function AppointmentCard({ appt, token, onChanged }) {
  const [busy, setBusy] = useState("");

  const act = async (action) => {
    setBusy(action);
    try {
      await api(`/appointments/${appt.appointmentId}/${action}`, { method: "POST", token });
      onChanged();
    } catch (e) {
      if (e.code === "AUTH") onChanged(e);
      else alert(e.message);
    } finally {
      setBusy("");
    }
  };

  const del = async () => {
    if (!window.confirm(`Permanently delete ${appt.name}'s appointment on ${appt.date} (${appt.time})? This cannot be undone.`)) return;
    setBusy("delete");
    try {
      await api(`/appointments/${appt.appointmentId}`, { method: "DELETE", token });
      onChanged();
    } catch (e) {
      if (e.code === "AUTH") onChanged(e);
      else alert(e.message);
    } finally {
      setBusy("");
    }
  };

  return (
    <div className="card">
      <div>
        <div className="name">{appt.name}{" "}
          <span className={`badge ${appt.status}`} style={{ marginLeft: 6 }}>{appt.status}</span>
        </div>
        <div className="svc">{appt.service}</div>
        <div className="meta">
          📅 {appt.date} · {appt.time}<br />
          📞 {appt.phone}{appt.email ? " · ✉️ " + appt.email : ""}
          {appt.notes ? <><br />📝 {appt.notes}</> : null}
        </div>
      </div>
      <div className="actions">
        {appt.status === "PENDING" && (
          <>
            <button className="btn btn-confirm" disabled={!!busy} onClick={() => act("confirm")}>
              {busy === "confirm" ? "…" : "Confirm"}
            </button>
            <button className="btn btn-cancel" disabled={!!busy} onClick={() => act("cancel")}>
              {busy === "cancel" ? "…" : "Cancel"}
            </button>
          </>
        )}
        <button className="btn btn-delete" disabled={!!busy} onClick={del}>
          {busy === "delete" ? "…" : "Delete"}
        </button>
      </div>
    </div>
  );
}

// ---------- Dashboard ----------
const TABS = ["PENDING", "CONFIRMED", "CANCELLED", "ALL"];

function Dashboard({ token, onSignOut }) {
  const [appointments, setAppointments] = useState([]);
  const [tab, setTab] = useState("PENDING");
  const [loading, setLoading] = useState(true);
  const [updatedAt, setUpdatedAt] = useState(null);
  const [error, setError] = useState("");

  const load = useCallback(async () => {
    try {
      const data = await api("/appointments", { token });
      setAppointments(data.appointments || []);
      setUpdatedAt(new Date());
      setError("");
    } catch (e) {
      if (e.code === "AUTH") { onSignOut(); return; }
      setError(e.message);
    } finally {
      setLoading(false);
    }
  }, [token, onSignOut]);

  // Initial load + poll every 30 seconds.
  useEffect(() => {
    load();
    const timer = setInterval(load, 30000);
    return () => clearInterval(timer);
  }, [load]);

  const counts = TABS.reduce((acc, t) => {
    acc[t] = t === "ALL" ? appointments.length : appointments.filter((a) => a.status === t).length;
    return acc;
  }, {});
  const visible = tab === "ALL" ? appointments : appointments.filter((a) => a.status === tab);

  return (
    <div className="wrap">
      <div className="head">
        <div>
          <h1>Appointments</h1>
          <div className="sub">
            <span className="live"><span className="pulse" /> Live · refreshes every 30s
              {updatedAt ? " · updated " + updatedAt.toLocaleTimeString() : ""}</span>
          </div>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <button className="btn btn-ghost" onClick={load}>Refresh</button>
          <button className="btn btn-ghost" onClick={onSignOut}>Sign out</button>
        </div>
      </div>

      <div className="tabs">
        {TABS.map((t) => (
          <button key={t} className={`tab ${tab === t ? "active" : ""}`} onClick={() => setTab(t)}>
            {t.charAt(0) + t.slice(1).toLowerCase()}<span className="count">{counts[t]}</span>
          </button>
        ))}
      </div>

      {error && <div className="err">{error}</div>}

      {loading ? (
        <div className="empty">Loading…</div>
      ) : visible.length === 0 ? (
        <div className="empty">No {tab.toLowerCase()} appointments.</div>
      ) : (
        visible.map((a) => (
          <AppointmentCard key={a.appointmentId} appt={a} token={token} onChanged={(e) => (e && e.code === "AUTH" ? onSignOut() : load())} />
        ))
      )}
    </div>
  );
}

// ---------- App shell ----------
function App() {
  const [token, setToken] = useState(() => localStorage.getItem(TOKEN_KEY) || null);

  const signOut = () => {
    localStorage.removeItem(TOKEN_KEY);
    setToken(null);
  };

  return (
    <>
      <div className="topbar">
        <div className="brand"><span className="dot">S</span> Shifa Dental · Staff</div>
        <a href="index.html" style={{ color: "#64798a", textDecoration: "none", fontSize: 14, fontWeight: 600 }}>← Back to site</a>
      </div>
      {token ? <Dashboard token={token} onSignOut={signOut} /> : <Login onToken={setToken} />}
    </>
  );
}

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