// src/server/smtp2go.ts
import "server-only"

type Smtp2goResponse<T> = {
  request_id?: string
  data?: T
  error?: string
  errors?: unknown
}

export type EmailBouncesData = {
  emails: number
  rejects: number
  softbounces: number
  hardbounces: number
  bounce_percent: string
}

export type EmailSummaryData = {
  [k: string]: unknown
}

export type RemoteSubaccount = {
  id?: string
  name?: string
  subaccount_id?: string
  subaccountId?: string
  state?: string
  label?: string
  smtp_username?: string
  smtpUsername?: string
  [k: string]: unknown
}

const BASE_URL = "https://api.smtp2go.com/v3"

function requireEnv(name: string) {
  const v = process.env[name]
  if (!v) throw new Error(`Missing env: ${name}`)
  return v
}

async function smtp2goPost<T>(
  path: string,
  body: Record<string, unknown>,
  opts?: { apiKey?: string }
): Promise<T> {
  const apiKey = opts?.apiKey ?? requireEnv("SMTP2GO_API_KEY")

  const res = await fetch(`${BASE_URL}${path}`, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ api_key: apiKey, ...body }),
    cache: "no-store",
  })

  const json = (await res.json().catch(() => ({}))) as Smtp2goResponse<T>

  if (!res.ok) {
    throw new Error(json?.error || `SMTP2GO_HTTP_${res.status}`)
  }

  const data = (json?.data ?? (json as unknown)) as T
  return data
}

export async function emailBounces(
  params: {
  username?: string
  subaccount_id?: string
  start_date?: string
  end_date?: string
  },
  opts?: { apiKey?: string }
) {
  return smtp2goPost<EmailBouncesData>("/stats/email_bounces", params, opts)
}

export async function emailSummary(
  params: {
  username?: string
  subaccount_id?: string
  start_date?: string
  end_date?: string
  },
  opts?: { apiKey?: string }
) {
  return smtp2goPost<EmailSummaryData>("/stats/email_summary", params, opts)
}

export async function emailSpam(
  params: { username?: string; subaccount_id?: string },
  opts?: { apiKey?: string }
) {
  const apiKey = opts?.apiKey ?? requireEnv("SMTP2GO_API_KEY")
  const res = await fetch(`${BASE_URL}/stats/email_spam`, {
    method: "POST",
    headers: {
      "content-type": "application/json",
      "accept": "application/json",
      "X-Smtp2go-Api-Key": apiKey,
    },
    body: JSON.stringify(params),
    cache: "no-store",
  })

  const json = (await res.json().catch(() => ({}))) as Smtp2goResponse<Record<string, unknown>>
  if (!res.ok) {
    throw new Error(json?.error || `SMTP2GO_HTTP_${res.status}`)
  }
  const data = (json?.data ?? (json as unknown)) as Record<string, unknown>
  return data
}

export async function viewSentEmails(params: {
  start_date?: string
  end_date?: string
  limit?: number
  username?: string
  subaccount_id?: string
  status_counts?: boolean
  opened_only?: boolean
  clicked_only?: boolean
  ignore_case?: boolean
  filter_query?: string | null
  email_id?: string[]
  headers?: string[]
  continue_token?: string
}) {
  return smtp2goPost<Record<string, unknown>>("/email/view", {
    limit: 5000,
    status_counts: false,
    opened_only: false,
    clicked_only: false,
    ignore_case: false,
    filter_query: null,
    headers: [],
    ...params,
  })
}

export type SubaccountsResponse = {
  subaccounts?: RemoteSubaccount[]
  continue_token?: string
  continueToken?: string
}

export async function searchSubaccounts(params: {
  fuzzy_search?: boolean
  search_terms?: string[]
  states?: string
  sort_direction?: string
  page_size?: number
  continue_token?: string
}) {
  return smtp2goPost<SubaccountsResponse>("/subaccounts/search", {
    fuzzy_search: true,
    sort_direction: "asc",
    page_size: 100,
    ...params,
  })
}

export type ApiKeyRecord = {
  api_key?: string
  username?: string
  description?: string
  status?: string
  [k: string]: unknown
}

export async function viewApiKeys(params: { id?: string; search?: string; subaccount_id?: string }) {
  return smtp2goPost<ApiKeyRecord[]>("/api_keys/view", params)
}

export async function addApiKey(params: {
  description?: string
  endpoints?: string[]
  status?: string
  subaccount_id?: string
  feedback_enabled?: boolean
  feedback_html?: string
  feedback_text?: string
  open_tracking_enabled?: boolean
  click_tracking_enabled?: boolean
  archive_enabled?: boolean
  audit_email?: string
  bounce_notifications?: string
  custom_ratelimit?: boolean
  custom_ratelimit_value?: number
  custom_ratelimit_period?: string
  ip_pool?: number
}) {
  return smtp2goPost<Record<string, unknown>>("/api_keys/add", params)
}

export type ActivitySearchParams = {
  start_date?: string
  end_date?: string
  search?: string
  search_email_id?: string
  search_subject?: string
  search_sender?: string
  search_recipient?: string
  search_usernames?: string[]
  subaccounts?: string[]
  limit?: number
  continue_token?: string
  only_latest?: boolean
  only_latest_by_sent?: boolean
  event_types?: string[]
  include_headers?: boolean
  custom_headers?: string[]
}

export type ActivitySearchResponse = {
  events?: Record<string, unknown>[]
  count?: number
  continue_token?: string
}

export async function activitySearch(params: ActivitySearchParams, opts?: { apiKey?: string }) {
  return smtp2goPost<ActivitySearchResponse>("/activity/search", params, opts)
}

export type EmailHistoryParams = {
  group_by?: "email_address" | "username" | "domain" | "subaccount"
  start_date?: string
  end_date?: string
  subaccounts?: string[]
}

export async function emailHistory(params: EmailHistoryParams, opts?: { apiKey?: string }) {
  return smtp2goPost<Record<string, unknown>>("/stats/email_history", params, opts)
}

export async function addSubaccount(params: {
  fullname: string
  limit?: number
  dedicated_ip?: boolean
  archiving?: boolean
  enforce_2fa?: boolean
  enable_sms?: boolean
  sms_limit?: number
}) {
  return smtp2goPost<Record<string, unknown>>("/subaccount/add", params)
}

export async function addSenderDomain(params: {
  domain: string
  tracking_subdomain?: string
  returnpath_subdomain?: string
  auto_verify?: boolean
  subaccount_id?: string
  subaccount_access?: Record<string, unknown>
}) {
  return smtp2goPost<Record<string, unknown>>("/domain/add", params)
}

export async function verifyDomain(params: { domain: string; subaccount_id?: string }) {
  return smtp2goPostWithHeader<Record<string, unknown>>("/domain/verify", params)
}

export async function editSubaccount(params: {
  id: string
  fullname?: string
  limit?: number
  dedicated_ip?: boolean
  archiving?: boolean
  enforce_2fa?: boolean
  enable_sms?: boolean
  sms_limit?: number
}) {
  return smtp2goPost<Record<string, unknown>>("/subaccount/edit", params)
}

export async function closeSubaccount(params: { id: string; email?: string }) {
  return smtp2goPost<Record<string, unknown>>("/subaccount/close", params)
}

export async function reopenSubaccount(params: { id: string; email?: string }) {
  return smtp2goPost<Record<string, unknown>>("/subaccount/reopen", params)
}

export type SmtpUserRecord = {
  username?: string
  description?: string
  email_password?: string
  sending_allowed?: boolean
  status?: string
  custom_ratelimit?: boolean
  custom_ratelimit_value?: number
  custom_ratelimit_period?: string
  feedback_enabled?: boolean
  ippool?: number
  open_tracking_enabled?: boolean
  click_tracking_enabled?: boolean
  archive_enabled?: boolean
  audit_email?: string
  bounce_notifications?: string
  default_ratelimit_period?: string
  [k: string]: unknown
}

export async function viewSmtpUsers(
  params: { subaccount_id: string },
  opts?: { apiKey?: string }
) {
  const apiKey = opts?.apiKey ?? requireEnv("SMTP2GO_API_KEY")
  const res = await fetch(`${BASE_URL}/users/smtp/view`, {
    method: "POST",
    headers: {
      "content-type": "application/json",
      "accept": "application/json",
      "X-Smtp2go-Api-Key": apiKey,
    },
    body: JSON.stringify({ subaccount_id: params.subaccount_id }),
    cache: "no-store",
  })

  const json = (await res.json().catch(() => ({}))) as Smtp2goResponse<{ results?: SmtpUserRecord[] }>
  if (!res.ok) {
    throw new Error(json?.error || `SMTP2GO_HTTP_${res.status}`)
  }
  const data = (json?.data ?? (json as unknown)) as { results?: SmtpUserRecord[] }
  return data
}

export async function viewDomains(
  params: { subaccount_id: string },
  opts?: { apiKey?: string }
) {
  return smtp2goPostWithHeader<Record<string, unknown>>("/domain/view", params, opts)
}

async function smtp2goPostWithHeader<T>(
  path: string,
  body: Record<string, unknown>,
  opts?: { apiKey?: string; method?: string }
): Promise<T> {
  const apiKey = opts?.apiKey ?? requireEnv("SMTP2GO_API_KEY")
  const res = await fetch(`${BASE_URL}${path}`, {
    method: opts?.method ?? "POST",
    headers: {
      "content-type": "application/json",
      "accept": "application/json",
      "X-Smtp2go-Api-Key": apiKey,
    },
    body: JSON.stringify(body),
    cache: "no-store",
  })

  const json = (await res.json().catch(() => ({}))) as Smtp2goResponse<T>
  if (!res.ok) {
    throw new Error(json?.error || `SMTP2GO_HTTP_${res.status}`)
  }
  const data = (json?.data ?? (json as unknown)) as T
  return data
}

export async function addSmtpUser(params: {
  subaccount_id: string
  username: string
  email_password?: string | null
  description?: string | null
  status?: string
  feedback_domain?: string
}) {
  return smtp2goPostWithHeader<Record<string, unknown>>("/users/smtp/add", params)
}

export async function editSmtpUser(params: {
  subaccount_id: string
  username: string
  email_password?: string | null
  description?: string | null
  status?: string | null
  feedback_enabled?: boolean | null
  feedback_html?: string | null
  feedback_text?: string | null
  open_tracking_enabled?: boolean | null
  click_tracking_enabled?: boolean | null
  archive_enabled?: boolean | null
  bounce_notifications?: string | null
}) {
  return smtp2goPostWithHeader<Record<string, unknown>>("/users/smtp/edit", params, { method: "PATCH" })
}

export async function removeSmtpUser(params: { subaccount_id: string; username: string }) {
  return smtp2goPostWithHeader<Record<string, unknown>>("/users/smtp/remove", params)
}
