const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api';

async function readJson<T>(response: Response): Promise<T> {
  const payload = await response.json();

  if (!response.ok) {
    const message =
      typeof payload?.message === 'string'
        ? payload.message
        : `Request failed with status ${response.status}`;
    throw new Error(message);
  }

  return payload as T;
}

export async function fetchDashboardSummary(token: string) {
  const response = await fetch(`${API_URL}/dashboard/summary`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    totalContacts: number;
    totalWebhookEvents: number;
    deliveredRate: number;
    webhookHealth: string;
  }>(response);
}

export async function fetchAnalyticsSummary(token: string) {
  const response = await fetch(`${API_URL}/dashboard/analytics-summary`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    generatedAt: string;
    queue: {
      pendingJobs: number;
      processingJobs: number;
      failedJobs24h: number;
    };
    workers: Array<{
      name: string;
      load: number;
      tone: 'success' | 'warning';
    }>;
    throughput: {
      perMinute: number;
      verifiedWebhookRate: number;
      jobsLastHour: number;
      webhooksLastHour: number;
    };
    metrics: {
      apiLatencyMs: number;
      apiLatencyBars: number[];
      databaseConnectionsEstimate: number;
      databaseUsagePercent: number;
      memoryUsageGbEstimate: number;
      memoryBars: number[];
    };
    totals: {
      totalJobs: number;
      totalWebhookEvents: number;
      pendingWebhookEvents: number;
      auditTrailTotal: number;
    };
    health: {
      status: string;
      database: string;
    };
  }>(response);
}

export async function fetchHealthStatus() {
  const response = await fetch(`${API_URL}/health`, {
    cache: 'no-store',
  });

  return readJson<{
    status: string;
    service: string;
    database: string;
    timestamp: string;
  }>(response);
}

export async function fetchCurrentSession(token: string) {
  const response = await fetch(`${API_URL}/auth/session`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    user: {
      id: string;
      name: string;
      email: string;
      status: string;
      lastLoginAt: string | null;
      twoFactorEnabled: boolean;
      twoFactorConfirmedAt: string | null;
    };
    session: {
      issuedAt: string | null;
      expiresAt: string | null;
      refreshExpiresAt: string | null;
      currentIp: string | null;
      policy: 'single-session';
    };
  }>(response);
}

export async function fetchTemplates(
  token: string,
  params?: {
    search?: string;
    category?: string;
    status?: string;
    language?: string;
  },
) {
  const query = new URLSearchParams();
  if (params?.search) query.set('search', params.search);
  if (params?.category) query.set('category', params.category);
  if (params?.status) query.set('status', params.status);
  if (params?.language) query.set('language', params.language);

  const response = await fetch(`${API_URL}/templates${query.size ? `?${query.toString()}` : ''}`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    total: number;
    items: Array<{
      id: string;
      name: string;
      category: string;
      status: string;
      language: string;
      updatedAt: string;
      updatedLabel: string;
      preview: string;
      compact: boolean;
      buttons: Array<{ type: string; label: string }>;
    }>;
  }>(response);
}

export async function fetchTemplateById(token: string, id: string) {
  const response = await fetch(`${API_URL}/templates/${id}`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    id: string;
    name: string;
    category: string;
    status: string;
    language: string;
    headerText: string | null;
    bodyText: string;
    footerText: string | null;
    buttons: Array<{ type: string; label: string }>;
    createdAt: string;
    updatedAt: string;
  }>(response);
}

export async function fetchConversations(
  token: string,
  params?: {
    filter?: 'all' | 'active' | 'pending';
    search?: string;
  },
) {
  const query = new URLSearchParams();
  if (params?.filter) query.set('filter', params.filter);
  if (params?.search) query.set('search', params.search);

  const response = await fetch(`${API_URL}/conversations${query.size ? `?${query.toString()}` : ''}`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<
    Array<{
      id: string;
      name: string;
      initials: string;
      time: string;
      status: string;
      tone: string;
      topic: string;
      snippet: string;
      online: boolean;
      location: string;
      email: string;
    phone: string;
    customerSince: string;
    tags: string[];
    lastActivityAt: string;
    unreadCount: number;
    assignedAgentName: string | null;
  }>
  >(response);
}

export async function fetchConversationDetail(token: string, contactId: string) {
  const response = await fetch(`${API_URL}/conversations/${contactId}`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    id: string;
    name: string;
    initials: string;
    time: string;
    status: string;
    tone: string;
    topic: string;
    snippet: string;
    online: boolean;
    location: string;
    email: string;
    phone: string;
    customerSince: string;
    tags: string[];
    lastActivityAt: string;
    unreadCount: number;
    assignedAgentName: string | null;
    activity: Array<{
      title: string;
      meta: string;
      tone: string;
    }>;
    messages: Array<{
      id: string;
      direction: 'incoming' | 'outgoing';
      body: string;
      time: string;
      status?: string;
    }>;
  }>(response);
}

export async function fetchContacts(token: string) {
  const response = await fetch(`${API_URL}/contacts`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<Array<{ id: string; name: string; phoneNumber: string }>>(response);
}

export async function fetchContactsDirectory(
  token: string,
  params?: {
    page?: number;
    limit?: number;
    search?: string;
    status?: string;
    tag?: string;
  },
) {
  const query = new URLSearchParams();
  if (params?.page) query.set('page', String(params.page));
  if (params?.limit) query.set('limit', String(params.limit));
  if (params?.search) query.set('search', params.search);
  if (params?.status) query.set('status', params.status);
  if (params?.tag) query.set('tag', params.tag);

  const response = await fetch(`${API_URL}/contacts${query.size ? `?${query.toString()}` : ''}`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    items: Array<{
      id: string;
      name: string;
      email: string | null;
      phoneNumber: string;
      company: string | null;
      status: 'Active' | 'Inactive';
      tags: string[];
      location: string;
      lastMessageAt: string | null;
      lastMessageLabel: string;
      lastSeenLabel: string;
      isBlacklisted: boolean;
      avatarInitials: string;
      createdAt: string;
      updatedAt: string;
    }>;
    total: number;
    page: number;
    pageSize: number;
    totalPages: number;
    availableTags: string[];
    statusCounts: {
      active: number;
      inactive: number;
    };
  }>(response);
}

export async function fetchContactDetail(token: string, id: string) {
  const response = await fetch(`${API_URL}/contacts/${id}`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    contact: {
      id: string;
      name: string;
      email: string | null;
      phoneNumber: string;
      company: string | null;
      status: 'Active' | 'Inactive';
      tags: string[];
      location: string;
      lastMessageAt: string | null;
      lastMessageLabel: string;
      lastSeenLabel: string;
      isBlacklisted: boolean;
      avatarInitials: string;
      createdAt: string;
      updatedAt: string;
      notes: Array<{
        id: string;
        author: string;
        dateLabel: string;
        body: string;
        emphasized: boolean;
      }>;
      history: Array<{
        id: string;
        type: string;
        title: string;
        at: string;
        summary: string;
        status: string;
        errorReason: string | null;
      }>;
    };
  }>(response);
}

export async function fetchWebhookLogs(token: string) {
  const response = await fetch(`${API_URL}/webhooks/logs`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<
    Array<{
      id: string;
      provider: string;
      eventId: string;
      eventType: string;
      senderPhone: string | null;
      recipientPhone: string | null;
      externalMessageId: string | null;
      eventTimestamp: string;
      payloadJson: unknown;
      verified: boolean;
      processingStatus: string;
      processingNotes: string | null;
      createdAt: string;
      updatedAt: string;
    }>
  >(response);
}

export async function fetchWhatsappSettings(token: string) {
  const response = await fetch(`${API_URL}/integrations/whatsapp`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    provider: string;
    webhookUrl: string;
    verifyToken: string;
    status: string;
    hasSharedSecret: boolean;
    hasAppSecret: boolean;
    hasAccessToken: boolean;
    phoneNumberId: string;
    isEnabled: boolean;
    subscriptions: string[];
    availableSubscriptions: Array<{
      key: string;
      label: string;
      description: string;
    }>;
  }>(response);
}

export async function fetchJobLogs(token: string) {
  const response = await fetch(`${API_URL}/logs/jobs?limit=20`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<
    Array<{
      id: string;
      queueName: string;
      jobType: string;
      status: string;
      attempts: number;
      maxAttempts: number;
      processedAt: string | null;
      createdAt: string;
    }>
  >(response);
}

export async function fetchAuditTrail(
  token: string,
  params?: {
    page?: number;
    limit?: number;
    range?: string;
    user?: string;
    actionType?: string;
    module?: string;
    search?: string;
  },
) {
  const query = new URLSearchParams();
  if (params?.page) query.set('page', String(params.page));
  if (params?.limit) query.set('limit', String(params.limit));
  if (params?.range) query.set('range', params.range);
  if (params?.user) query.set('user', params.user);
  if (params?.actionType) query.set('actionType', params.actionType);
  if (params?.module) query.set('module', params.module);
  if (params?.search) query.set('search', params.search);

  const response = await fetch(`${API_URL}/logs/audit-trail${query.size ? `?${query.toString()}` : ''}`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    items: Array<{
      id: string;
      actorUserId: string | null;
      actorName: string;
      actorEmail: string | null;
      actionType: string;
      module: string;
      ipAddress: string | null;
      severity: 'default' | 'alert';
      details: string;
      metadataJson: unknown;
      createdAt: string;
    }>;
    total: number;
    page: number;
    pageSize: number;
    totalPages: number;
  }>(response);
}

export async function fetchRoles(token: string) {
  const response = await fetch(`${API_URL}/roles`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<
    Array<{
      id: string;
      key: string;
      name: string;
      summary: string;
      badge: string;
      tone: 'primary' | 'secondary' | 'tertiary';
      icon: string;
      usersAssigned: number;
      permissions: Array<{
        id: string;
        label: string;
        icon: string;
        description: string;
        values: Record<string, boolean | null>;
      }>;
    }>
  >(response);
}

export async function fetchUsers(
  token: string,
  params?: {
    page?: number;
    limit?: number;
    search?: string;
    roleId?: string;
    status?: string;
  },
) {
  const query = new URLSearchParams();
  if (params?.page) query.set('page', String(params.page));
  if (params?.limit) query.set('limit', String(params.limit));
  if (params?.search) query.set('search', params.search);
  if (params?.roleId) query.set('roleId', params.roleId);
  if (params?.status) query.set('status', params.status);

  const response = await fetch(`${API_URL}/users${query.size ? `?${query.toString()}` : ''}`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<
    {
      items: Array<{
        id: string;
        name: string;
        email: string;
        status: 'invited' | 'active' | 'inactive' | 'suspended';
        roleId: string | null;
        roleName: string;
        createdAt: string;
        updatedAt: string;
        lastLoginAt: string | null;
        emailVerifiedAt: string | null;
      }>;
      total: number;
      page: number;
      pageSize: number;
      totalPages: number;
    }
  >(response);
}

export async function fetchCampaigns(token: string) {
  const response = await fetch(`${API_URL}/campaigns`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    metrics: {
      totalMessages: number;
      averageDeliveryRate: number;
      scheduledCount: number;
      failedDeliveries: number;
    };
    items: Array<{
      id: string;
      code: string;
      name: string;
      audience: string;
      audienceGroup: string;
      sent: string;
      opened: string;
      status: 'Sent' | 'Scheduled' | 'Draft' | 'Failed';
      deliveryRate: number | null;
      dateLabel: string;
      timeLabel: string;
      templateName: string | null;
    }>;
  }>(response);
}

export async function fetchCampaignDetail(
  token: string,
  id: string,
  params?: {
    page?: number;
    limit?: number;
  },
) {
  const query = new URLSearchParams();
  if (params?.page) query.set('page', String(params.page));
  if (params?.limit) query.set('limit', String(params.limit));

  const response = await fetch(`${API_URL}/campaigns/${id}${query.size ? `?${query.toString()}` : ''}`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    campaign: {
      id: string;
      code: string;
      name: string;
      status: string;
      initiatedAt: string;
      totalRecipients: number;
      deliveredCount: number;
      deliveredRate: number;
      readCount: number;
      readRate: number;
      failedCount: number;
      failedRate: number;
      templateName: string;
      language: string;
      messageTitle: string;
      messageBody: string;
      primaryButton: string;
      secondaryButton: string;
      bannerImageUrl: string;
    };
    timeline: Array<{
      label: string;
      count: number;
      height: number;
    }>;
    recipients: {
      items: Array<{
        id: string;
        phoneNumber: string;
        status: string;
        sentAt: string | null;
        errorReason: string | null;
        deviceOs: string | null;
      }>;
      total: number;
      page: number;
      pageSize: number;
      totalPages: number;
    };
    deviceBreakdown: Array<{
      label: string;
      count: number;
      percentage: number;
    }>;
  }>(response);
}

export async function fetchInvitation(token: string) {
  const response = await fetch(`${API_URL}/users/invitations/${token}`, {
    cache: 'no-store',
  });

  return readJson<{
    email: string;
    name: string;
    roleName: string;
    expiresAt: string | null;
  }>(response);
}

export async function fetchPasswordResetRequest(token: string) {
  const response = await fetch(`${API_URL}/auth/password-reset/${token}`, {
    cache: 'no-store',
  });

  return readJson<{
    email: string;
    name: string;
    expiresAt: string | null;
  }>(response);
}

export async function fetchTwoFactorStatus(token: string) {
  const response = await fetch(`${API_URL}/auth/2fa/status`, {
    headers: { Authorization: `Bearer ${token}` },
    cache: 'no-store',
  });

  return readJson<{
    enabled: boolean;
    pendingSetup: boolean;
    confirmedAt: string | null;
    recoveryCodesRemaining: number;
  }>(response);
}
