/**
 * API client for the admin dashboard.
 * Fetches from Next.js API routes which connect directly to Cosmos DB.
 * Falls back gracefully when API is unavailable (e.g., no Cosmos configured).
 */

const API_BASE = '/api';

function getBaseUrl(): string {
  if (typeof window === 'undefined') return '';
  return window.location.origin;
}

function getAuthHeaders(): HeadersInit {
  if (typeof window === 'undefined') return {};
  const headers: Record<string, string> = {};
  const token = localStorage.getItem('admin_access_token');
  if (token) headers['Authorization'] = `Bearer ${token}`;
  const productId = localStorage.getItem('admin_selected_product');
  if (productId) headers['x-product-id'] = productId;
  return headers;
}

export async function apiFetch<T>(
  path: string,
  options: RequestInit = {}
): Promise<{ data: T | null; error: string | null }> {
  try {
    const res = await fetch(`${API_BASE}${path}`, {
      ...options,
      headers: {
        'Content-Type': 'application/json',
        ...getAuthHeaders(),
        ...options.headers,
      },
    });

    if (!res.ok) {
      const body = await res.json().catch(() => ({ error: res.statusText }));
      return { data: null, error: body.error || `HTTP ${res.status}` };
    }

    const data = await res.json();
    return { data, error: null };
  } catch {
    return { data: null, error: 'API unavailable' };
  }
}

// ── Auth ────────────────────────────────────────────────────────────

export interface LoginResponse {
  accessToken: string;
  refreshToken: string;
  user: {
    id: string;
    email: string;
    name: string;
    role: string;
    plan: string;
  };
}

export async function apiLogin(email: string, password: string) {
  return apiFetch<LoginResponse>('/auth/login', {
    method: 'POST',
    body: JSON.stringify({ email, password }),
  });
}

export async function apiGetMe() {
  return apiFetch<{
    id: string;
    email: string;
    name: string;
    role: string;
    plan: string;
    status: string;
  }>('/auth/me');
}

// ── Users ───────────────────────────────────────────────────────────

export interface ApiUser {
  id: string;
  email: string;
  name: string;
  role: string;
  plan: string;
  status: string;
  createdAt: string;
  lastActive: string;
  totalTokensUsed: number;
  totalRequests: number;
  monthlySpend: number;
}

export async function apiListUsers(limit = 100, offset = 0) {
  return apiFetch<{ users: ApiUser[]; total: number; byPlan: Record<string, number> }>(
    `/users?limit=${limit}&offset=${offset}`
  );
}

export async function apiCreateUser(body: {
  email: string;
  name: string;
  password: string;
  role?: string;
  plan?: string;
}) {
  return apiFetch<ApiUser>('/users', {
    method: 'POST',
    body: JSON.stringify(body),
  });
}

export async function apiUpdateUser(id: string, body: Record<string, unknown>) {
  return apiFetch<ApiUser>(`/users/${id}`, {
    method: 'PUT',
    body: JSON.stringify(body),
  });
}

export async function apiDeleteUser(id: string) {
  return apiFetch<{ success: boolean }>(`/users/${id}`, { method: 'DELETE' });
}

// ── Tokens ──────────────────────────────────────────────────────────

export interface ApiToken {
  id: string;
  userId: string;
  userName: string;
  name: string;
  prefix: string;
  status: string;
  scopes: string[];
  createdAt: string;
  expiresAt: string;
  lastUsed: string | null;
}

export async function apiListTokens() {
  return apiFetch<{ tokens: ApiToken[] }>('/tokens');
}

export async function apiCreateToken(body: {
  name: string;
  scopes?: string[];
  expiresInDays?: number;
}) {
  return apiFetch<ApiToken & { rawToken: string }>('/tokens', {
    method: 'POST',
    body: JSON.stringify(body),
  });
}

export async function apiRevokeToken(id: string) {
  return apiFetch<{ success: boolean }>(`/tokens/${id}`, {
    method: 'PATCH',
    body: JSON.stringify({ action: 'revoke' }),
  });
}

export async function apiDeleteToken(id: string) {
  return apiFetch<{ success: boolean }>(`/tokens/${id}`, { method: 'DELETE' });
}

// ── Subscriptions / Plans ───────────────────────────────────────────

export interface PlanDoc {
  id: string;
  productId: string;
  name: string;
  displayName: string;
  price: number;
  tokens: number;
  words: number;
  dictations: number;
  features: string[];
  stripePriceId?: string;
  active: boolean;
  createdAt: string;
  updatedAt: string;
}

export async function apiListPlans() {
  return apiFetch<{ plans: PlanDoc[] }>('/settings/plans');
}

export interface PlanUpdate {
  price?: number;
  tokensPerMonth?: number;
  requestsPerDay?: number;
}

export async function apiUpdatePlan(planId: string, body: PlanUpdate) {
  return apiFetch<{ success: boolean; plan: string }>(`/settings/plans/${planId}`, {
    method: 'PUT',
    body: JSON.stringify(body),
  });
}

export interface NewPlan {
  name: string;
  price: number;
  tokensPerMonth: number;
  requestsPerDay: number;
  yearlyDiscount?: boolean;
}

export async function apiCreatePlan(body: NewPlan) {
  return apiFetch<{ success: boolean; plan: string }>('/settings/plans', {
    method: 'POST',
    body: JSON.stringify(body),
  });
}

// ── Revenue Analytics ───────────────────────────────────────────────

export interface RevenueAnalytics {
  mrr: number;
  arr: number;
  mrrChange: number;
  totalRevenue: number;
  revenueByMonth: Array<{ month: string; revenue: number; subscriptions: number }>;
  churnRate: number;
  churnCount: number;
  ltv: number;
  arpu: number;
  newSubscriptions: number;
  canceledSubscriptions: number;
}

export async function apiGetRevenueAnalytics(months = 6) {
  return apiFetch<RevenueAnalytics>(`/analytics/revenue?months=${months}`);
}

// ── Usage ───────────────────────────────────────────────────────────

export interface ApiUsageRecord {
  id: string;
  userId: string;
  date: string;
  dictations: number;
  words: number;
  durationMs: number;
  tokensUsed: number;
  costUsd: number;
  model?: string;
  source?: string;
}

export interface ApiModelBreakdown {
  model: string;
  tokens: number;
  requests: number;
  cost: number;
}

export interface ApiSourceBreakdown {
  source: string;
  tokens: number;
  requests: number;
  cost: number;
}

export interface ApiProductBreakdown {
  productId: string;
  tokens: number;
  requests: number;
  cost: number;
}

export async function apiGetUsage(days = 30, userId?: string, productId?: string) {
  const params = new URLSearchParams({ days: String(days) });
  if (userId) params.set('userId', userId);
  if (productId) params.set('productId', productId);
  return apiFetch<{
    records?: ApiUsageRecord[];
    totalWords?: number;
    totalDictations?: number;
    totalTokens?: number;
    totalCost?: number;
  }>(`/usage?${params}`);
}

export async function apiGetUsageSummary(days = 30, userId?: string, productId?: string) {
  const params = new URLSearchParams({ days: String(days), summary: 'true' });
  if (userId) params.set('userId', userId);
  if (productId) params.set('productId', productId);
  return apiFetch<{
    totalWords: number;
    totalDictations: number;
    totalTokens: number;
    totalCost: number;
    records: ApiUsageRecord[];
    modelBreakdown: ApiModelBreakdown[];
    sourceBreakdown?: ApiSourceBreakdown[];
    productBreakdown?: ApiProductBreakdown[];
  }>(`/usage?${params}`);
}

// ── Audit ───────────────────────────────────────────────────────────

export interface ApiAuditEntry {
  id: string;
  category: string;
  action: string;
  actor: string;
  target: string;
  ip: string;
  timestamp: string;
}

export async function apiGetAudit(category?: string, limit = 100) {
  const params = new URLSearchParams({ limit: String(limit) });
  if (category) params.set('category', category);
  return apiFetch<{ entries: ApiAuditEntry[]; total: number }>(`/audit?${params}`);
}

export async function apiGetAuditSummary() {
  return apiFetch<{ total: number; failedLogins: number }>('/audit?summary=true');
}

// ── Dashboard Stats ─────────────────────────────────────────────────

export interface DashboardStats {
  users: { total: number; byPlan: Record<string, number> };
  tokens: { active: number };
  usage: { totalWords: number; totalDictations: number; totalCost: number };
  audit: { total: number; failedLogins: number };
}

export async function apiGetDashboardStats() {
  return apiFetch<DashboardStats>('/dashboard/stats');
}

// ── Invitations ────────────────────────────────────────────────────

export interface ApiInvitation {
  id: string;
  code: string;
  description: string;
  createdBy: string;
  grantPlan: 'pro' | 'enterprise';
  grantTrialDays: number;
  bonusTokens: number;
  maxUses: number;
  currentUses: number;
  redeemedBy: string[];
  status: 'active' | 'expired' | 'disabled';
  expiresAt: string | null;
  createdAt: string;
  updatedAt: string;
}

export async function apiListInvitations(limit = 100, offset = 0) {
  return apiFetch<{ codes: ApiInvitation[]; total: number }>(
    `/invitations?limit=${limit}&offset=${offset}`
  );
}

export async function apiCreateInvitation(body: {
  code?: string;
  description?: string;
  grantPlan?: string;
  grantTrialDays?: number;
  bonusTokens?: number;
  maxUses?: number;
  expiresAt?: string | null;
}) {
  return apiFetch<ApiInvitation>('/invitations', {
    method: 'POST',
    body: JSON.stringify(body),
  });
}

export async function apiUpdateInvitation(id: string, body: Record<string, unknown>) {
  return apiFetch<ApiInvitation>(`/invitations/${id}`, {
    method: 'PATCH',
    body: JSON.stringify(body),
  });
}

export async function apiDeleteInvitation(id: string) {
  return apiFetch<{ success: boolean }>(`/invitations/${id}`, { method: 'DELETE' });
}

export interface BulkInviteResult {
  total: number;
  created: number;
  failed: number;
  invitations: ApiInvitation[];
  errors: { index: number; error: string }[];
}

export async function apiBulkCreateInvitations(
  invitations: Array<{
    code: string;
    description?: string;
    createdBy: string;
    grantPlan: string;
    grantTrialDays?: number;
    bonusTokens?: number;
    maxUses?: number;
    expiresAt?: string | null;
  }>
) {
  return apiFetch<BulkInviteResult>('/invitations/bulk', {
    method: 'POST',
    body: JSON.stringify(invitations),
  });
}

// ── Promos (Stripe) ────────────────────────────────────────────────

export interface ApiPromo {
  id: string;
  code: string;
  active: boolean;
  couponId: string;
  percentOff: number | null;
  amountOff: number | null;
  currency: string | null;
  duration: string | null;
  timesRedeemed: number;
  maxRedemptions: number | null;
  expiresAt: string | null;
  created: string;
  metadata: Record<string, string>;
}

export async function apiListPromos(active?: boolean) {
  const params = active !== undefined ? `?active=${active}` : '';
  return apiFetch<{ promos: ApiPromo[] }>(`/promos${params}`);
}

export async function apiCreatePromo(body: {
  code: string;
  percentOff?: number;
  amountOff?: number;
  currency?: string;
  duration?: string;
  durationInMonths?: number;
  maxRedemptions?: number;
  expiresAt?: string;
}) {
  return apiFetch<ApiPromo>('/promos', {
    method: 'POST',
    body: JSON.stringify(body),
  });
}

export async function apiDeletePromo(id: string) {
  return apiFetch<{ success: boolean }>(`/promos/${id}`, { method: 'DELETE' });
}

export async function apiUpdatePromo(id: string, body: { active?: boolean }) {
  return apiFetch<ApiPromo>(`/promos/${id}`, {
    method: 'PATCH',
    body: JSON.stringify(body),
  });
}

// ── Referrals ──────────────────────────────────────────────────────

export interface ApiReferral {
  id: string;
  referrerId: string;
  referrerEmail: string;
  referredUserId: string | null;
  referredEmail: string;
  status: 'pending' | 'signed_up' | 'subscribed' | 'rewarded';
  referrerRewardTokens: number;
  referredRewardTokens: number;
  referrerRewarded: boolean;
  referredRewarded: boolean;
  createdAt: string;
  completedAt: string | null;
}

export interface ReferralStats {
  total: number;
  completed: number;
  rewarded: number;
}

export async function apiListReferrals(limit = 100, offset = 0) {
  return apiFetch<{ referrals: ApiReferral[]; stats: ReferralStats }>(
    `/referrals?limit=${limit}&offset=${offset}`
  );
}

export async function apiGetReferralStats() {
  return apiFetch<ReferralStats>('/referrals?mode=summary');
}

// ── Cohort Retention Analysis ────────────────────────────────────────

export interface RetentionCohort {
  cohortWeek: string;
  cohortStart: string;
  signups: number;
  retained7d: number;
  retained14d: number;
  retained30d: number;
  rate7d: number;
  rate14d: number;
  rate30d: number;
}

export async function apiGetRetention(weeks = 8) {
  return apiFetch<{
    cohorts: RetentionCohort[];
    totalUsers: number;
    weeksAnalyzed: number;
  }>(`/analytics/retention?weeks=${weeks}`);
}

// ── User Impersonation (read-only view) ─────────────────────────────

export interface UserViewResponse {
  profile: ApiUser & { role: string; productId: string };
  usage: {
    records: ApiUsageRecord[];
    totalWords?: number;
    totalDictations?: number;
    totalTokens?: number;
    totalCost?: number;
  };
  viewedBy: { id: string; name: string; role: string };
  viewedAt: string;
}

export async function apiGetUserView(userId: string) {
  return apiFetch<UserViewResponse>(`/users/${userId}/view`);
}

// ── Seed ────────────────────────────────────────────────────────────

export async function apiSeed(secret: string) {
  return apiFetch<{ success: boolean; message: string }>(`/seed?secret=${secret}`, {
    method: 'POST',
  });
}

// ── Broadcasts ─────────────────────────────────────────────────────

export interface ApiBroadcast {
  id: string;
  title: string;
  body: string;
  bodyMarkdown?: string;
  ctaText?: string;
  ctaUrl?: string;
  imageUrl?: string;
  target: {
    userSegments?: string[];
    platforms?: string[];
    appVersionMin?: string;
    appVersionMax?: string;
    countryCodes?: string[];
    regionCodes?: string[];
    osVersionMin?: string;
    osVersionMax?: string;
    percentageRollout?: number;
    specificUserIds?: string[];
  };
  channels: ('push' | 'in_app' | 'email')[];
  status: 'draft' | 'scheduled' | 'sending' | 'sent' | 'paused';
  scheduledAt?: string;
  sentAt?: string;
  variant?: 'control' | 'treatment';
  experimentId?: string;
  parentBroadcastId?: string;
  metrics: {
    targetedCount: number;
    sentCount: number;
    deliveredCount: number;
    openedCount: number;
    clickedCount: number;
    dismissedCount: number;
    convertedCount: number;
  };
  createdAt: string;
  updatedAt: string;
  createdBy: string;
}

export async function apiListBroadcasts(status?: ApiBroadcast['status']) {
  const params = status ? `?status=${status}` : '';
  return apiFetch<{ broadcasts: ApiBroadcast[]; total: number }>(`/admin/broadcasts${params}`);
}

export async function apiGetBroadcast(id: string) {
  return apiFetch<ApiBroadcast>(`/admin/broadcasts/${id}`);
}

export async function apiCreateBroadcast(
  body: Omit<ApiBroadcast, 'id' | 'metrics' | 'createdAt' | 'updatedAt' | 'createdBy'>
) {
  return apiFetch<ApiBroadcast>('/admin/broadcasts', {
    method: 'POST',
    body: JSON.stringify(body),
  });
}

export async function apiUpdateBroadcast(id: string, body: Partial<ApiBroadcast>) {
  return apiFetch<ApiBroadcast>(`/admin/broadcasts/${id}`, {
    method: 'PUT',
    body: JSON.stringify(body),
  });
}

export async function apiDeleteBroadcast(id: string) {
  return apiFetch<{ success: boolean }>(`/admin/broadcasts/${id}`, { method: 'DELETE' });
}

export async function apiCloneBroadcast(id: string, variant?: 'control' | 'treatment') {
  return apiFetch<ApiBroadcast>(`/admin/broadcasts/${id}/clone`, {
    method: 'POST',
    body: JSON.stringify({ variant }),
  });
}

export async function apiSendBroadcast(id: string) {
  return apiFetch<{ success: boolean }>(`/admin/broadcasts/${id}/send`, { method: 'POST' });
}

export async function apiPauseBroadcast(id: string) {
  return apiFetch<{ success: boolean }>(`/admin/broadcasts/${id}/pause`, { method: 'POST' });
}

export async function apiGetBroadcastMetrics(id: string) {
  return apiFetch<{
    broadcastId: string;
    metrics: ApiBroadcast['metrics'];
    status: ApiBroadcast['status'];
  }>(`/admin/broadcasts/${id}/metrics`);
}

export async function apiEstimateBroadcastReach(target: ApiBroadcast['target']) {
  return apiFetch<{
    estimatedCount: number;
    targetBreakdown: {
      userSegments: Record<string, number>;
      platforms: Record<string, number>;
      countries: Record<string, number>;
    };
    sampleUserIds: string[];
  }>('/admin/broadcasts/estimate-reach', {
    method: 'POST',
    body: JSON.stringify(target),
  });
}

// ── Surveys ────────────────────────────────────────────────────────

export interface ApiSurvey {
  id: string;
  title: string;
  description?: string;
  questions: {
    id: string;
    type:
      | 'single_choice'
      | 'multiple_choice'
      | 'rating'
      | 'nps'
      | 'text_short'
      | 'text_long'
      | 'dropdown'
      | 'scale'
      | 'ranking';
    text: string;
    description?: string;
    required: boolean;
    options?: { id: string; text: string; emoji?: string }[];
    showIf?: unknown;
    minLength?: number;
    maxLength?: number;
    minValue?: number;
    maxValue?: number;
  }[];
  target: ApiBroadcast['target'];
  status: 'draft' | 'active' | 'paused' | 'closed';
  startsAt?: string;
  endsAt?: string;
  displayTrigger:
    | { type: 'immediate' }
    | { type: 'delay_seconds'; seconds: number }
    | { type: 'event'; eventName: string }
    | { type: 'page_view'; pagePattern: string };
  incentive?: { type: 'pro_days' | 'credits'; amount: number };
  metrics: {
    impressions: number;
    starts: number;
    completions: number;
    avgTimeSeconds: number;
    incentiveClaims: number;
  };
  createdAt: string;
  updatedAt: string;
  createdBy: string;
}

export interface ApiSurveyResponse {
  id: string;
  surveyId: string;
  userId: string;
  answers: Record<string, unknown>;
  currentQuestionIndex: number;
  startedAt: string;
  completedAt?: string;
  isComplete: boolean;
  incentiveClaimed: boolean;
  createdAt: string;
}

export interface ApiSurveyAnalytics {
  totalStarts: number;
  totalCompletions: number;
  completionRate: number;
  avgTimeSeconds: number;
  questionAnalytics: {
    questionId: string;
    questionType: string;
    totalResponses: number;
    optionCounts?: Record<string, number>;
    average?: number;
    min?: number;
    max?: number;
    distribution?: Record<number, number>;
    sampleResponses?: string[];
  }[];
  computedMetrics: {
    completionRate: number;
  };
}

export async function apiListSurveys(status?: ApiSurvey['status']) {
  const params = status ? `?status=${status}` : '';
  return apiFetch<{ surveys: ApiSurvey[]; total: number }>(`/admin/surveys${params}`);
}

export async function apiGetSurvey(id: string) {
  return apiFetch<ApiSurvey>(`/admin/surveys/${id}`);
}

export async function apiCreateSurvey(
  body: Omit<ApiSurvey, 'id' | 'metrics' | 'createdAt' | 'updatedAt' | 'createdBy'>
) {
  return apiFetch<ApiSurvey>('/admin/surveys', {
    method: 'POST',
    body: JSON.stringify(body),
  });
}

export async function apiUpdateSurvey(id: string, body: Partial<ApiSurvey>) {
  return apiFetch<ApiSurvey>(`/admin/surveys/${id}`, {
    method: 'PUT',
    body: JSON.stringify(body),
  });
}

export async function apiDeleteSurvey(id: string) {
  return apiFetch<{ success: boolean }>(`/admin/surveys/${id}`, { method: 'DELETE' });
}

export async function apiDuplicateSurvey(id: string) {
  return apiFetch<ApiSurvey>(`/admin/surveys/${id}/duplicate`, { method: 'POST' });
}

export async function apiPauseSurvey(id: string) {
  return apiFetch<{ success: boolean }>(`/admin/surveys/${id}/pause`, { method: 'POST' });
}

export async function apiGetSurveyResponses(
  id: string,
  options?: { isComplete?: boolean; limit?: number; offset?: number }
) {
  const params = new URLSearchParams();
  if (options?.isComplete !== undefined) params.set('isComplete', String(options.isComplete));
  if (options?.limit) params.set('limit', String(options.limit));
  if (options?.offset) params.set('offset', String(options.offset));
  return apiFetch<{ responses: ApiSurveyResponse[]; total: number }>(
    `/admin/surveys/${id}/responses?${params}`
  );
}

export async function apiGetSurveyRespondents(id: string) {
  return apiFetch<{ userIds: string[]; count: number }>(`/admin/surveys/${id}/respondents`);
}

export async function apiGetSurveyAnalytics(id: string) {
  return apiFetch<ApiSurveyAnalytics>(`/admin/surveys/${id}/analytics`);
}

export async function apiExportSurveyCSV(id: string): Promise<string> {
  const res = await fetch(`${getBaseUrl()}/admin/surveys/${id}/export.csv`, {
    headers: getAuthHeaders(),
  });
  if (!res.ok) throw new Error(`Export failed: ${res.status}`);
  return res.text();
}
