// @File: src/lib/cpanelApi.ts
// @Desc: Typed fetch wrappers for the WHM/cPanel Reseller Manager module.
//        Follows the same pattern as bizmailApi.ts — authenticated with
//        the app JWT from localStorage, JSON error envelopes parsed into
//        a single string message.
import { getToken } from "@/lib/auth";

// ---------- helpers ----------
function authHeaders(extra?: Record<string, string>): HeadersInit {
  const token = getToken();
  return {
    "Content-Type": "application/json",
    ...(token ? { Authorization: `Bearer ${token}` } : {}),
    ...(extra ?? {}),
  };
}

async function handle<T>(res: Response): Promise<T> {
  const raw = await res.text();
  let data: unknown = null;
  if (raw) {
    try {
      data = JSON.parse(raw);
    } catch {
      data = raw;
    }
  }
  if (!res.ok) {
    const detail =
      data && typeof data === "object" && "detail" in (data as Record<string, unknown>)
        ? String((data as Record<string, unknown>).detail)
        : null;
    throw new Error(detail || res.statusText || "Request failed");
  }
  return data as T;
}

// ---------- types ----------
export interface CpanelServer {
  id: number;
  name: string;
  hostname: string;
  port: number;
  username: string;
  verify_tls: boolean;
  is_active: boolean;
  notes: string | null;
  last_tested_at: string | null;
  last_test_status: string | null;
  last_test_message: string | null;
  created_at: string;
  updated_at: string;
}

export interface CpanelServerCreate {
  name: string;
  hostname: string;
  port: number;
  username: string;
  api_token: string;
  verify_tls: boolean;
  is_active: boolean;
  notes?: string | null;
}

export type CpanelServerUpdate = Partial<CpanelServerCreate>;

export interface CpanelServerTestResult {
  ok: boolean;
  message: string;
  whm_version?: string | null;
}

export interface CpanelPackage {
  id: number;
  server_id: number;
  display_name: string;
  slug: string;
  description: string | null;
  monthly_price: string;
  currency: string;
  whmcs_product_id: number | null;
  whm_package_name: string;
  disk_quota_mb: number | null;
  bandwidth_mb: number | null;
  max_email_accounts: number | null;
  max_ftp_accounts: number | null;
  max_databases: number | null;
  max_subdomains: number | null;
  max_addon_domains: number | null;
  max_parked_domains: number | null;
  has_ssl: boolean;
  has_backup: boolean;
  has_ssh: boolean;
  has_wordpress_tools: boolean;
  has_cloudlinux: boolean;
  cpu_limit_percent: number | null;
  memory_limit_mb: number | null;
  io_limit_kbps: number | null;
  iops_limit: number | null;
  ep_limit: number | null;
  nproc_limit: number | null;
  is_active: boolean;
  sort_order: number;
  created_at: string;
  updated_at: string;
}

export type CpanelPackageCreate = Omit<CpanelPackage, "id" | "created_at" | "updated_at">;
export type CpanelPackageUpdate = Partial<CpanelPackageCreate>;

export interface CpanelAccount {
  id: number;
  user_id: string;
  server_id: number;
  package_id: number | null;
  whmcs_service_id: number | null;
  whmcs_client_id: number | null;
  cpanel_username: string;
  main_domain: string;
  contact_email: string | null;
  status: string;
  suspend_reason: string | null;
  last_error: string | null;
  provisioned_at: string | null;
  suspended_at: string | null;
  unsuspended_at: string | null;
  terminated_at: string | null;
  created_at: string;
  updated_at: string;
}

export interface CpanelAccountUsage {
  disk_used_mb: number | null;
  disk_limit_mb: number | null;
  bandwidth_used_mb: number | null;
  bandwidth_limit_mb: number | null;
  email_accounts: number | null;
  ftp_accounts: number | null;
  databases: number | null;
  subdomains: number | null;
  addon_domains: number | null;
  ssl_status: string | null;
  backup_status: string | null;
  cpu_used_percent: number | null;
  memory_used_mb: number | null;
  entry_processes: number | null;
  last_synced_at: string | null;
}

export interface CpanelAccountDetail extends CpanelAccount {
  server_hostname: string | null;
  package_name: string | null;
  usage: CpanelAccountUsage | null;
}

export interface CpanelAccountActionResult {
  ok: boolean;
  message: string;
  account?: CpanelAccount;
}

export interface CpanelSsoResult {
  url: string;
  expires_in_seconds: number;
}

export interface SimpleItem { name: string; extra?: string | null }
export interface QuickActionResult { ok: boolean; message: string }

export interface CpanelPackageSyncResult {
  ok: boolean;
  imported: number;
  updated: number;
  items: string[];
  message?: string | null;
}

export interface CpanelApiLogEntry {
  id: number;
  server_id: number | null;
  account_id: number | null;
  endpoint: string;
  method: string;
  status: string;
  http_status: number | null;
  duration_ms: number | null;
  request_preview: string | null;
  response_preview: string | null;
  error_message: string | null;
  created_at: string;
}

export interface CpanelAuditEntry {
  id: number;
  action: string;
  admin_user_id: string | null;
  admin_email: string | null;
  account_id: number | null;
  target_user_id: string | null;
  details: string | null;
  created_at: string;
}

export interface CpanelOrphanAccount {
  cpanel_username: string;
  main_domain: string;
  package?: string | null;
  server_id: number;
}

// ---------- endpoints ----------
const ADMIN = "/api/v1/admin/cpanel";
const CLIENT = "/api/v1/client/cpanel";

async function req<T>(path: string, init?: RequestInit): Promise<T> {
  const res = await fetch(path, { ...(init ?? {}), headers: authHeaders(init?.headers as Record<string, string>) });
  return handle<T>(res);
}

export const cpanelAdmin = {
  listServers: () => req<CpanelServer[]>(`${ADMIN}/servers`),
  createServer: (body: CpanelServerCreate) =>
    req<CpanelServer>(`${ADMIN}/servers`, { method: "POST", body: JSON.stringify(body) }),
  updateServer: (id: number, body: CpanelServerUpdate) =>
    req<CpanelServer>(`${ADMIN}/servers/${id}`, { method: "PATCH", body: JSON.stringify(body) }),
  deleteServer: (id: number) =>
    fetch(`${ADMIN}/servers/${id}`, { method: "DELETE", headers: authHeaders() }).then((r) => {
      if (!r.ok) throw new Error(r.statusText || "Delete failed");
    }),
  testServer: (id: number) =>
    req<CpanelServerTestResult>(`${ADMIN}/servers/${id}/test`, { method: "POST" }),

  listPackages: (serverId?: number) => {
    const qs = serverId ? `?server_id=${serverId}` : "";
    return req<CpanelPackage[]>(`${ADMIN}/packages${qs}`);
  },
  createPackage: (body: CpanelPackageCreate) =>
    req<CpanelPackage>(`${ADMIN}/packages`, { method: "POST", body: JSON.stringify(body) }),
  updatePackage: (id: number, body: CpanelPackageUpdate) =>
    req<CpanelPackage>(`${ADMIN}/packages/${id}`, { method: "PATCH", body: JSON.stringify(body) }),
  deletePackage: (id: number) =>
    fetch(`${ADMIN}/packages/${id}`, { method: "DELETE", headers: authHeaders() }).then((r) => {
      if (!r.ok) throw new Error(r.statusText || "Delete failed");
    }),
  syncPackagesFromWhm: (serverId: number) =>
    req<CpanelPackageSyncResult>(`${ADMIN}/packages/sync/${serverId}`, { method: "POST" }),

  listAccounts: (params?: { status?: string; server_id?: number }) => {
    const qs = new URLSearchParams();
    if (params?.status) qs.set("status", params.status);
    if (params?.server_id) qs.set("server_id", String(params.server_id));
    const suffix = qs.toString() ? `?${qs.toString()}` : "";
    return req<CpanelAccount[]>(`${ADMIN}/accounts${suffix}`);
  },
  getAccount: (id: number) => req<CpanelAccountDetail>(`${ADMIN}/accounts/${id}`),
  createAccount: (body: {
    user_id: string;
    server_id: number;
    package_id: number;
    main_domain: string;
    contact_email?: string;
    whmcs_service_id?: number;
    whmcs_client_id?: number;
  }) => req<CpanelAccountActionResult>(`${ADMIN}/accounts`, { method: "POST", body: JSON.stringify(body) }),
  suspend: (id: number, reason?: string) => {
    const qs = reason ? `?reason=${encodeURIComponent(reason)}` : "";
    return req<CpanelAccountActionResult>(`${ADMIN}/accounts/${id}/suspend${qs}`, { method: "POST" });
  },
  unsuspend: (id: number) =>
    req<CpanelAccountActionResult>(`${ADMIN}/accounts/${id}/unsuspend`, { method: "POST" }),
  terminate: (id: number) =>
    req<CpanelAccountActionResult>(`${ADMIN}/accounts/${id}/terminate`, { method: "POST" }),
  changePackage: (id: number, newPackageId: number) =>
    req<CpanelAccountActionResult>(`${ADMIN}/accounts/${id}/change-package`, {
      method: "POST",
      body: JSON.stringify({ new_package_id: newPackageId }),
    }),
  adminSso: (id: number) => req<CpanelSsoResult>(`${ADMIN}/accounts/${id}/sso`, { method: "POST" }),

  listOrphans: (serverId: number) => req<CpanelOrphanAccount[]>(`${ADMIN}/orphans/${serverId}`),
  linkOrphan: (body: {
    user_id: string;
    server_id: number;
    cpanel_username: string;
    main_domain: string;
    package_id?: number;
    whmcs_service_id?: number;
    whmcs_client_id?: number;
  }) => req<CpanelAccount>(`${ADMIN}/orphans/link`, { method: "POST", body: JSON.stringify(body) }),

  listApiLogs: (params?: { server_id?: number; status?: string; limit?: number }) => {
    const qs = new URLSearchParams();
    if (params?.server_id) qs.set("server_id", String(params.server_id));
    if (params?.status) qs.set("status", params.status);
    if (params?.limit) qs.set("limit", String(params.limit));
    const suffix = qs.toString() ? `?${qs.toString()}` : "";
    return req<CpanelApiLogEntry[]>(`${ADMIN}/api-logs${suffix}`);
  },
  listAuditLog: (limit = 200) => req<CpanelAuditEntry[]>(`${ADMIN}/audit-log?limit=${limit}`),
};

export const cpanelClient = {
  listMyAccounts: () => req<CpanelAccount[]>(`${CLIENT}/accounts`),
  getAccount: (id: number) => req<CpanelAccountDetail>(`${CLIENT}/accounts/${id}`),
  syncUsage: (id: number) =>
    req<CpanelAccountUsage>(`${CLIENT}/accounts/${id}/sync-usage`, { method: "POST" }),
  sso: (id: number) => req<CpanelSsoResult>(`${CLIENT}/accounts/${id}/sso`, { method: "POST" }),

  listEmails: (id: number) => req<SimpleItem[]>(`${CLIENT}/accounts/${id}/emails`),
  createEmail: (id: number, body: { email: string; password: string; quota_mb: number }) =>
    req<QuickActionResult>(`${CLIENT}/accounts/${id}/emails`, { method: "POST", body: JSON.stringify(body) }),
  deleteEmail: (id: number, email: string) =>
    req<QuickActionResult>(`${CLIENT}/accounts/${id}/emails/${encodeURIComponent(email)}`, { method: "DELETE" }),

  listFtp: (id: number) => req<SimpleItem[]>(`${CLIENT}/accounts/${id}/ftp`),
  createFtp: (id: number, body: { username: string; password: string; quota_mb: number; homedir?: string }) =>
    req<QuickActionResult>(`${CLIENT}/accounts/${id}/ftp`, { method: "POST", body: JSON.stringify(body) }),
  deleteFtp: (id: number, username: string) =>
    req<QuickActionResult>(`${CLIENT}/accounts/${id}/ftp/${encodeURIComponent(username)}`, { method: "DELETE" }),

  listDatabases: (id: number) => req<SimpleItem[]>(`${CLIENT}/accounts/${id}/mysql/databases`),
  createDatabase: (id: number, dbName: string) =>
    req<QuickActionResult>(`${CLIENT}/accounts/${id}/mysql/databases`, {
      method: "POST",
      body: JSON.stringify({ db_name: dbName }),
    }),
  deleteDatabase: (id: number, dbName: string) =>
    req<QuickActionResult>(`${CLIENT}/accounts/${id}/mysql/databases/${encodeURIComponent(dbName)}`, {
      method: "DELETE",
    }),
  createDbUser: (id: number, username: string, password: string) =>
    req<QuickActionResult>(`${CLIENT}/accounts/${id}/mysql/users`, {
      method: "POST",
      body: JSON.stringify({ username, password }),
    }),

  listSubdomains: (id: number) => req<SimpleItem[]>(`${CLIENT}/accounts/${id}/subdomains`),
  createSubdomain: (id: number, body: { subdomain: string; parent_domain: string; docroot?: string }) =>
    req<QuickActionResult>(`${CLIENT}/accounts/${id}/subdomains`, { method: "POST", body: JSON.stringify(body) }),

  listSsl: (id: number) => req<SimpleItem[]>(`${CLIENT}/accounts/${id}/ssl`),
  listBackups: (id: number) => req<SimpleItem[]>(`${CLIENT}/accounts/${id}/backups`),
};

export const cpanelPublic = {
  listPackages: () => req<CpanelPackage[]>(`/api/v1/public/cpanel/packages`),
};