/**
 * Communication Platform API — Torbat Communication (real backend only).
 * Browser → /api/communication BFF; SSR → direct upstream :8005
 */

import { getValidAccessToken, refreshSession } from "@/lib/auth";
import type {
  CapabilitiesRawResponse,
  HealthResponse,
  MetricsResponse,
  MonitoringMetrics,
  MonitoringStats,
  CommunicationListParams,
} from "@/modules/communication/types";

const COMM_BASE =
  typeof window !== "undefined"
    ? "/api/communication"
    : process.env.COMMUNICATION_SERVICE_URL ||
      process.env.NEXT_PUBLIC_COMMUNICATION_API_URL ||
      "http://localhost:8005";

export class CommunicationApiError extends Error {
  constructor(
    public status: number,
    public code: string,
    message: string
  ) {
    super(message);
    this.name = "CommunicationApiError";
  }
}

type RequestOptions = RequestInit & { tenantId: string; auth?: boolean };

async function request<T>(path: string, options: RequestOptions): Promise<T> {
  const { tenantId, auth = true, headers: customHeaders, ...init } = options;
  const headers = new Headers(customHeaders);
  if (!headers.has("Content-Type") && init.body) {
    headers.set("Content-Type", "application/json");
  }
  headers.set("X-Tenant-ID", tenantId);
  if (auth) {
    let token = await getValidAccessToken();
    if (!token) {
      token = await refreshSession({ force: true });
    }
    if (!token) {
      throw new CommunicationApiError(
        401,
        "unauthorized",
        "توکن احراز هویت یافت نشد. لطفاً دوباره وارد شوید."
      );
    }
    headers.set("Authorization", `Bearer ${token}`);
  }

  const url = path.startsWith("http")
    ? path
    : `${COMM_BASE.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;

  let res: Response;
  try {
    res = await fetch(url, { ...init, headers });
  } catch (err) {
    const detail = err instanceof Error ? err.message : "network_error";
    throw new Error(`اتصال به سرویس تربت ارتباط برقرار نشد (${url}) — ${detail}`);
  }

  if (res.status === 401 && auth) {
    const refreshed = await refreshSession({ force: true });
    if (refreshed) {
      headers.set("Authorization", `Bearer ${refreshed}`);
      res = await fetch(url, { ...init, headers });
    }
  }

  if (!res.ok) {
    const body = await res.json().catch(() => ({}));
    throw new CommunicationApiError(
      res.status,
      body?.error?.code || body?.detail || "unknown_error",
      body?.error?.message || body?.detail || res.statusText
    );
  }
  if (res.status === 204) return undefined as T;
  return res.json() as Promise<T>;
}

function qs(params?: CommunicationListParams) {
  if (!params) return "";
  const sp = new URLSearchParams();
  Object.entries(params).forEach(([k, v]) => {
    if (v !== undefined && v !== null && v !== "") sp.set(k, String(v));
  });
  const s = sp.toString();
  return s ? `?${s}` : "";
}

export const communicationApi = {
  health: (): Promise<HealthResponse> =>
    fetch(`${COMM_BASE}/health`).then((r) => r.json()),

  healthReady: (): Promise<{ status: string; database: string }> =>
    fetch(`${COMM_BASE}/health/ready`).then((r) => r.json()),

  capabilities: (): Promise<CapabilitiesRawResponse> =>
    fetch(`${COMM_BASE}/capabilities`).then((r) => r.json()),

  metrics: (): Promise<MetricsResponse> =>
    fetch(`${COMM_BASE}/metrics`).then((r) => r.json()),

  providers: {
    list: (tenantId: string) =>
      request<Record<string, unknown>[]>("/api/v1/providers", { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(`/api/v1/providers/${id}`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>("/api/v1/providers", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
    update: (tenantId: string, id: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>(`/api/v1/providers/${id}`, {
        tenantId,
        method: "PATCH",
        body: JSON.stringify(body),
      }),
    remove: (tenantId: string, id: string) =>
      request<void>(`/api/v1/providers/${id}`, { tenantId, method: "DELETE" }),
    status: (tenantId: string) =>
      request<Record<string, unknown>[]>("/api/v1/providers/status", { tenantId }),
    balance: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(`/api/v1/providers/${id}/balance`, { tenantId }),
    healthCheck: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(`/api/v1/providers/${id}/health`, {
        tenantId,
        method: "POST",
      }),
    senders: {
      list: (tenantId: string) =>
        request<Record<string, unknown>[]>("/api/v1/providers/senders/list", { tenantId }),
      create: (tenantId: string, body: Record<string, unknown>) =>
        request<Record<string, unknown>>("/api/v1/providers/senders", {
          tenantId,
          method: "POST",
          body: JSON.stringify(body),
        }),
    },
  },

  templates: {
    list: (tenantId: string) =>
      request<Record<string, unknown>[]>("/api/v1/templates", { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(`/api/v1/templates/${id}`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>("/api/v1/templates", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
    submit: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(`/api/v1/templates/${id}/submit`, {
        tenantId,
        method: "POST",
      }),
    approve: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(`/api/v1/templates/${id}/approve`, {
        tenantId,
        method: "POST",
      }),
    reject: (tenantId: string, id: string, reason?: string) =>
      request<Record<string, unknown>>(
        `/api/v1/templates/${id}/reject${reason ? qs({ reason }) : ""}`,
        { tenantId, method: "POST" }
      ),
    preview: (tenantId: string, id: string, variables: Record<string, unknown>) =>
      request<{ rendered: string; subject?: string }>(`/api/v1/templates/${id}/preview`, {
        tenantId,
        method: "POST",
        body: JSON.stringify({ variables }),
      }),
  },

  contacts: {
    manual: {
      list: (tenantId: string) =>
        request<Record<string, unknown>[]>("/api/v1/contacts/manual", { tenantId }),
      create: (tenantId: string, body: Record<string, unknown>) =>
        request<Record<string, unknown>>("/api/v1/contacts/manual", {
          tenantId,
          method: "POST",
          body: JSON.stringify(body),
        }),
      importCsv: (tenantId: string, body: { csv_text: string }) =>
        request<Record<string, unknown>[]>("/api/v1/contacts/manual/import-csv", {
          tenantId,
          method: "POST",
          body: JSON.stringify(body),
        }),
    },
    sources: {
      list: (tenantId: string) =>
        request<Record<string, unknown>[]>("/api/v1/contacts/sources", { tenantId }),
      create: (tenantId: string, body: Record<string, unknown>) =>
        request<Record<string, unknown>>("/api/v1/contacts/sources", {
          tenantId,
          method: "POST",
          body: JSON.stringify(body),
        }),
    },
    resolve: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>[]>("/api/v1/contacts/resolve", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
  },

  messages: {
    send: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>[]>("/api/v1/messages/send", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
    list: (tenantId: string, params?: CommunicationListParams) =>
      request<Record<string, unknown>[]>(`/api/v1/messages${qs(params)}`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(`/api/v1/messages/${id}`, { tenantId }),
    stats: (tenantId: string) =>
      request<Record<string, unknown>>("/api/v1/messages/stats", { tenantId }),
    timeline: (tenantId: string, id: string) =>
      request<Record<string, unknown>[]>(`/api/v1/messages/${id}/timeline`, { tenantId }),
    cancel: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(`/api/v1/messages/${id}/cancel`, {
        tenantId,
        method: "POST",
      }),
    queue: {
      process: (tenantId: string, limit = 20) =>
        request<{ processed: number }>(`/api/v1/messages/queue/process${qs({ limit })}`, {
          tenantId,
          method: "POST",
        }),
      deadLetters: (tenantId: string) =>
        request<Record<string, unknown>[]>("/api/v1/messages/queue/dead-letters", { tenantId }),
      stats: (tenantId: string) =>
        request<Record<string, unknown>>("/api/v1/messages/queue/stats", { tenantId }),
    },
  },

  otp: {
    request: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>("/api/v1/otp/request", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
    verify: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>("/api/v1/otp/verify", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
  },

  monitoring: {
    stats: (tenantId: string) =>
      request<MonitoringStats>("/api/v1/monitoring/stats", { tenantId }),
    metrics: (tenantId: string) =>
      request<MonitoringMetrics>("/api/v1/monitoring/metrics", { tenantId }),
  },
};

export function normalizeCapabilities(raw: CapabilitiesRawResponse) {
  const features: Record<string, boolean> = {};
  for (const f of raw.features ?? []) features[f] = true;
  for (const ch of raw.channels ?? []) {
    features[`channel_${ch.channel}`] = ch.status === "active";
  }
  return {
    ...raw,
    commercial_product: "Torbat Communication",
    phase: "8",
    features,
  };
}
