import { useEffect, useRef, useState } from "react";
import { api } from "../api/client";
import type { AuthResponse, SyncStatus } from "../types/api";

function syncProgressLabel(status: SyncStatus): string {
  const { detail_fill_progress: fill, activities_pending_details: pending } = status;
  if (fill.Total > 0) {
    // pending includes the current batch, so subtract what's already
    // counted in this batch's Total to avoid double-counting the "beyond
    // this batch" remainder.
    const beyondBatch = Math.max(0, pending - (fill.Total - fill.Done));
    return `syncing: ${fill.Done}/${fill.Total} activities${beyondBatch > 0 ? ` (+${beyondBatch} more queued)` : ""}`;
  }
  return "syncing...";
}

export function GarminConnection() {
  const [auth, setAuth] = useState<AuthResponse | null>(null);
  const [code, setCode] = useState("");
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [syncStatus, setSyncStatus] = useState<SyncStatus | null>(null);

  function refreshStatus() {
    api.authStatus().then(setAuth).catch((e) => setError(String(e)));
    api.syncStatus().then(setSyncStatus).catch(() => {});
  }

  // Poll faster while a sync is actually running, so progress feels live;
  // back off to a relaxed interval the rest of the time.
  const syncStatusRef = useRef(syncStatus);
  syncStatusRef.current = syncStatus;

  useEffect(() => {
    refreshStatus();
    let timeout: ReturnType<typeof setTimeout>;
    const tick = () => {
      refreshStatus();
      timeout = setTimeout(tick, syncStatusRef.current?.in_progress ? 1500 : 6000);
    };
    timeout = setTimeout(tick, 1500);
    return () => clearTimeout(timeout);
  }, []);

  async function connect() {
    setBusy(true);
    setError(null);
    try {
      setAuth(await api.login());
    } catch (e) {
      setError(String(e));
    } finally {
      setBusy(false);
    }
  }

  async function submitMFA() {
    if (!code.trim()) return;
    setBusy(true);
    setError(null);
    try {
      setAuth(await api.submitMFA(code.trim()));
      setCode("");
    } catch (e) {
      setError(String(e));
    } finally {
      setBusy(false);
    }
  }

  async function sync() {
    setBusy(true);
    setError(null);
    try {
      await api.syncRun();
      refreshStatus();
    } catch (e) {
      setError(String(e));
    } finally {
      setBusy(false);
    }
  }

  async function resetAll() {
    if (!window.confirm("This deletes every synced activity, lap, and kind assignment, then starts a fresh pull from Garmin next sync. This cannot be undone. Continue?")) {
      return;
    }
    setBusy(true);
    setError(null);
    try {
      await api.resetSync();
      // Reset runs as a background sync job; wait for it to actually finish
      // before reloading, otherwise other pages (e.g. Review Queue) would
      // still show the just-deleted activities from their own stale state.
      let status = await api.syncStatus();
      while (status.in_progress) {
        await new Promise((resolve) => setTimeout(resolve, 300));
        status = await api.syncStatus();
      }
      window.location.reload();
    } catch (e) {
      setError(String(e));
      setBusy(false);
    }
  }

  const status = auth?.status ?? "unknown";

  return (
    <div className="garmin-connection">
      <div className="garmin-connection-row">
        <span className={`status-dot status-${status}`} />
        <span className="status-label">
          {status === "authenticated" && "Connected to Garmin"}
          {status === "mfa_required" && "MFA code required"}
          {status === "failed" && "Connection failed"}
          {status === "unknown" && "Not connected to Garmin"}
        </span>

        {status !== "authenticated" && status !== "mfa_required" && (
          <button disabled={busy} onClick={connect}>
            Connect to Garmin
          </button>
        )}

        {status === "authenticated" && (
          <>
            <button disabled={busy} onClick={sync}>
              Sync now
            </button>
            <button className="button-danger" disabled={busy} onClick={resetAll}>
              Reset all
            </button>
            {syncStatus?.in_progress && (
              <span className="status-label">{syncProgressLabel(syncStatus)}</span>
            )}
            {syncStatus?.last_run && !syncStatus.in_progress && (
              <span className="status-label">
                last sync: {syncStatus.last_run.Status} ({syncStatus.last_run.ActivitiesFetched} activities)
                {syncStatus.activities_pending_details > 0 &&
                  ` — ${syncStatus.activities_pending_details} still need details, click Sync now again`}
              </span>
            )}
          </>
        )}
      </div>

      {status === "mfa_required" && (
        <div className="garmin-connection-row">
          <input
            placeholder="MFA code"
            value={code}
            onChange={(e) => setCode(e.target.value)}
            onKeyDown={(e) => e.key === "Enter" && submitMFA()}
          />
          <button disabled={busy} onClick={submitMFA}>
            Submit code
          </button>
        </div>
      )}

      {auth?.message && <p className="garmin-connection-message">{auth.message}</p>}
      {error && <p className="error">{error}</p>}
    </div>
  );
}
