import * as React from 'react';
import { useAuth } from '@/lib/auth';
import { TokenManager } from '@sentryagent/idp-sdk';

/** Shape of the GET /api/v1/billing/usage response. */
interface UsageResponse {
  tenantId: string;
  date: string;
  apiCalls: number;
  agentCount: number;
  subscriptionStatus: string;
  currentPeriodEnd: string | null;
  stripeSubscriptionId: string | null;
}

type LoadState = 'idle' | 'loading' | 'success' | 'error';

interface UsageState {
  loadState: LoadState;
  data: UsageResponse | null;
  errorMessage: string | null;
}

const initialState: UsageState = {
  loadState: 'idle',
  data: null,
  errorMessage: null,
};

/**
 * Fetches the current usage summary from the API using the stored credentials.
 *
 * @param baseUrl - The API base URL.
 * @param clientId - The agent client ID.
 * @param clientSecret - The agent client secret.
 * @returns The usage response from the server.
 */
async function fetchUsage(
  baseUrl: string,
  clientId: string,
  clientSecret: string,
): Promise<UsageResponse> {
  const tokenManager = new TokenManager(
    baseUrl,
    clientId,
    clientSecret,
    'agents:read',
  );
  const token = await tokenManager.getToken();

  const response = await fetch(`${baseUrl}/api/v1/billing/usage`, {
    headers: { Authorization: `Bearer ${token}` },
  });

  if (!response.ok) {
    throw new Error(`Failed to fetch usage data (HTTP ${response.status})`);
  }

  return response.json() as Promise<UsageResponse>;
}

/** Badge shown for the tenant's subscription tier. */
function SubscriptionBadge({ status }: { status: string }): React.JSX.Element {
  const isPro = status !== 'free';

  return (
    <span
      className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold ${
        isPro
          ? 'bg-brand-100 text-brand-700'
          : 'bg-slate-100 text-slate-600'
      }`}
    >
      {isPro ? 'Pro' : 'Free Tier'}
    </span>
  );
}

/** A single metric card with label and value. */
function MetricCard({ label, value }: { label: string; value: string | number }): React.JSX.Element {
  return (
    <div className="rounded-xl border border-slate-200 bg-white p-6 shadow-sm">
      <p className="text-sm font-medium text-slate-500">{label}</p>
      <p className="mt-1 text-2xl font-bold text-slate-900">{value}</p>
    </div>
  );
}

/**
 * Displays the current tenant's usage summary:
 * - API calls today
 * - Active agent count
 * - Subscription status (Free Tier / Pro)
 *
 * Fetches GET /api/v1/billing/usage with the current Bearer token.
 * Handles loading state and error state gracefully.
 */
export function UsagePanel(): React.JSX.Element {
  const { credentials } = useAuth();
  const [state, setState] = React.useState<UsageState>(initialState);

  const loadUsage = React.useCallback(async (): Promise<void> => {
    if (!credentials) return;

    setState((prev) => ({ ...prev, loadState: 'loading', errorMessage: null }));

    try {
      const data = await fetchUsage(
        credentials.baseUrl,
        credentials.clientId,
        credentials.clientSecret,
      );
      setState({ loadState: 'success', data, errorMessage: null });
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Unknown error occurred.';
      setState({ loadState: 'error', data: null, errorMessage: message });
    }
  }, [credentials]);

  React.useEffect(() => {
    void loadUsage();
  }, [loadUsage]);

  const isLoading = state.loadState === 'loading' || state.loadState === 'idle';

  return (
    <div>
      <div className="mb-6 flex items-center justify-between">
        <h1 className="text-2xl font-bold text-slate-900">Usage &amp; Billing</h1>
        <button
          onClick={() => { void loadUsage(); }}
          disabled={isLoading}
          className="rounded-md border border-slate-300 px-3 py-1.5 text-sm hover:bg-slate-50 disabled:opacity-40"
        >
          Refresh
        </button>
      </div>

      {/* Error state */}
      {state.loadState === 'error' && (
        <div className="mb-6 rounded-md bg-red-50 px-4 py-3 text-sm text-red-700" role="alert">
          {state.errorMessage ?? 'Failed to load usage data.'}
        </div>
      )}

      {/* Loading skeleton */}
      {isLoading && (
        <div className="grid grid-cols-1 gap-4 sm:grid-cols-3 animate-pulse">
          {[1, 2, 3].map((i) => (
            <div key={i} className="h-28 rounded-xl border border-slate-200 bg-slate-100" />
          ))}
        </div>
      )}

      {/* Data */}
      {state.loadState === 'success' && state.data !== null && (
        <>
          <div className="mb-4 flex items-center gap-3">
            <p className="text-sm text-slate-500">
              Showing usage for <strong>{state.data.date}</strong>
            </p>
            <SubscriptionBadge status={state.data.subscriptionStatus} />
          </div>

          <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
            <MetricCard label="API Calls Today" value={state.data.apiCalls.toLocaleString()} />
            <MetricCard label="Active Agents" value={state.data.agentCount.toLocaleString()} />
            <MetricCard label="Plan" value={state.data.subscriptionStatus === 'free' ? 'Free Tier' : 'Pro'} />
          </div>

          {state.data.subscriptionStatus === 'free' && (
            <div className="mt-6 rounded-xl border border-brand-200 bg-brand-50 p-5">
              <p className="text-sm font-medium text-brand-800">
                You are on the Free Tier — limited to 10 agents and 1,000 API calls/day.
              </p>
              <p className="mt-1 text-sm text-brand-700">
                Upgrade to Pro for unlimited agents and API calls.
              </p>
            </div>
          )}

          {state.data.currentPeriodEnd !== null && (
            <p className="mt-4 text-xs text-slate-400">
              Current period ends:{' '}
              {new Date(state.data.currentPeriodEnd).toLocaleDateString()}
            </p>
          )}
        </>
      )}
    </div>
  );
}
