/**
 * Sports Center Service API client — real backend only.
 * Browser → /api/sports-center BFF; SSR → direct upstream :8006
 */

import { getValidAccessToken, refreshSession } from "@/lib/auth";
import type { CapabilitiesResponse, HealthResponse, ListParams } from "@/modules/sports-center/types";

const SPORTS_CENTER_BASE =
  typeof window !== "undefined"
    ? "/api/sports-center"
    : process.env.SPORTS_CENTER_SERVICE_URL ||
      process.env.NEXT_PUBLIC_SPORTS_CENTER_API_URL ||
      "http://localhost:8006";

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

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) {
    const token = await getValidAccessToken();
    if (token) headers.set("Authorization", `Bearer ${token}`);
  }

  const url = path.startsWith("http")
    ? path
    : `${SPORTS_CENTER_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 SportsCenterApiError(
      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?: ListParams) {
  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}` : "";
}

function action(tenantId: string, apiPath: string, body?: Record<string, unknown>) {
  return request<Record<string, unknown>>(apiPath, {
    tenantId,
    method: "POST",
    body: body ? JSON.stringify(body) : undefined,
  });
}

function crud(basePath: string, opts?: { upsert?: boolean }) {
  return {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(`${basePath}${qs(params)}`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(`${basePath}/${id}`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>(basePath, {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
    update: (tenantId: string, id: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>(`${basePath}/${id}`, {
        tenantId,
        method: "PATCH",
        body: JSON.stringify(body),
      }),
    remove: (tenantId: string, id: string) =>
      action(tenantId, `${basePath}/${id}/delete`),
    upsert: opts?.upsert
      ? (tenantId: string, body: Record<string, unknown>) =>
          request<Record<string, unknown>>(basePath, {
            tenantId,
            method: "PUT",
            body: JSON.stringify(body),
          })
      : undefined,
  };
}

function createOnly(basePath: string) {
  return {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(`${basePath}${qs(params)}`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>(basePath, {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
  };
}

function postOnly(basePath: string) {
  return {
    list: async (_tenantId: string, _params?: ListParams) => [] as Record<string, unknown>[],
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>(basePath, {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
  };
}

function listOnly(basePath: string) {
  return {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(`${basePath}${qs(params)}`, { tenantId }),
  };
}

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

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

  // Foundation
  sportsCenters: crud("/api/v1/sports-centers"),
  branches: crud("/api/v1/branches"),
  sports: crud("/api/v1/sports"),
  membershipTypes: crud("/api/v1/membership-types"),
  memberships: {
    ...crud("/api/v1/memberships"),
    assignMember: (tenantId: string, id: string, body: Record<string, unknown>) =>
      action(tenantId, `/api/v1/memberships/${id}/assign-member`, body),
    activate: (tenantId: string, id: string, body?: Record<string, unknown>) =>
      action(tenantId, `/api/v1/memberships/${id}/activate`, body),
    suspend: (tenantId: string, id: string, body?: Record<string, unknown>) =>
      action(tenantId, `/api/v1/memberships/${id}/suspend`, body),
    cancel: (tenantId: string, id: string, body?: Record<string, unknown>) =>
      action(tenantId, `/api/v1/memberships/${id}/cancel`, body),
    freeze: (tenantId: string, id: string, body: Record<string, unknown>) =>
      action(tenantId, `/api/v1/memberships/${id}/freeze`, body),
    unfreeze: (tenantId: string, id: string, body?: Record<string, unknown>) =>
      action(tenantId, `/api/v1/memberships/${id}/unfreeze`, body),
  },
  coaches: crud("/api/v1/coaches"),
  roles: crud("/api/v1/roles"),
  permissions: crud("/api/v1/permissions"),
  facilities: crud("/api/v1/facilities"),
  courts: crud("/api/v1/courts"),
  rooms: crud("/api/v1/rooms"),
  lockerRooms: crud("/api/v1/locker-rooms"),
  lockers: {
    ...crud("/api/v1/lockers"),
    assign: (tenantId: string, id: string, body: Record<string, unknown>) =>
      action(tenantId, `/api/v1/lockers/${id}/assign`, body),
    release: (tenantId: string, id: string, body?: Record<string, unknown>) =>
      action(tenantId, `/api/v1/lockers/${id}/release`, body),
  },
  deviceProviders: crud("/api/v1/device-providers"),
  devices: {
    ...crud("/api/v1/devices"),
    connect: (tenantId: string, id: string) => action(tenantId, `/api/v1/devices/${id}/connect`),
    disconnect: (tenantId: string, id: string) => action(tenantId, `/api/v1/devices/${id}/disconnect`),
  },
  attendanceGateways: crud("/api/v1/attendance-gateways"),
  configurations: crud("/api/v1/configurations"),
  events: crud("/api/v1/events"),
  settings: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(`/api/v1/settings${qs(params)}`, { tenantId }),
    upsert: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>("/api/v1/settings", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
    remove: (tenantId: string, id: string) => action(tenantId, `/api/v1/settings/${id}/delete`),
  },

  // Catalog
  sportCategories: crud("/api/v1/sport-categories"),
  ageGroups: crud("/api/v1/age-groups"),
  pricingModels: crud("/api/v1/pricing-models"),
  membershipPackages: crud("/api/v1/membership-packages"),
  membershipPlans: crud("/api/v1/membership-plans"),
  membershipRules: crud("/api/v1/membership-rules"),
  renewalPolicies: crud("/api/v1/renewal-policies"),
  freezingRules: crud("/api/v1/freezing-rules"),
  expirationPolicies: crud("/api/v1/expiration-policies"),

  // Members
  members: crud("/api/v1/members"),
  familyMembers: crud("/api/v1/family-members"),
  emergencyContacts: crud("/api/v1/emergency-contacts"),
  medicalInformation: {
    upsert: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>("/api/v1/medical-information", {
        tenantId,
        method: "PUT",
        body: JSON.stringify(body),
      }),
    byMember: (tenantId: string, memberId: string) =>
      request<Record<string, unknown>>(`/api/v1/medical-information/by-member/${memberId}`, { tenantId }),
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(`/api/v1/members${qs(params)}`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>("/api/v1/medical-information", {
        tenantId,
        method: "PUT",
        body: JSON.stringify(body),
      }),
  },
  membershipCards: {
    ...createOnly("/api/v1/membership-cards"),
    revoke: (tenantId: string, id: string) => action(tenantId, `/api/v1/membership-cards/${id}/revoke`),
  },
  digitalMemberships: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(`/api/v1/digital-memberships${qs(params)}`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>("/api/v1/digital-memberships", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
    update: (tenantId: string, id: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>(`/api/v1/digital-memberships/${id}`, {
        tenantId,
        method: "PATCH",
        body: JSON.stringify(body),
      }),
  },
  waivers: {
    ...createOnly("/api/v1/waivers"),
    sign: (tenantId: string, id: string, body?: Record<string, unknown>) =>
      action(tenantId, `/api/v1/waivers/${id}/sign`, body),
  },
  memberDocuments: createOnly("/api/v1/member-documents"),

  // Staff
  staffCertificates: createOnly("/api/v1/staff-certificates"),
  staffSkills: createOnly("/api/v1/staff-skills"),
  staffWorkingHours: createOnly("/api/v1/staff-working-hours"),
  staffAvailability: createOnly("/api/v1/staff-availability"),
  staffAssignments: createOnly("/api/v1/staff-assignments"),

  // Booking
  equipment: createOnly("/api/v1/equipment"),
  sessions: createOnly("/api/v1/sessions"),
  bookings: {
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>("/api/v1/bookings", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
    confirm: (tenantId: string, id: string) => action(tenantId, `/api/v1/bookings/${id}/confirm`),
    cancel: (tenantId: string, id: string, body?: Record<string, unknown>) =>
      action(tenantId, `/api/v1/bookings/${id}/cancel`, body),
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(`/api/v1/sessions${qs(params)}`, { tenantId }),
  },
  waitingList: createOnly("/api/v1/waiting-list"),
  resourceReservations: createOnly("/api/v1/resource-reservations"),

  // Attendance
  checkIn: (tenantId: string, body: Record<string, unknown>) =>
    action(tenantId, "/api/v1/check-in", body),
  checkOut: (tenantId: string, body: Record<string, unknown>) =>
    action(tenantId, "/api/v1/check-out", body),
  attendanceRecords: createOnly("/api/v1/attendance-records"),
  accessLogs: listOnly("/api/v1/access-logs"),

  // Training
  trainingPrograms: createOnly("/api/v1/training-programs"),
  exercises: postOnly("/api/v1/exercises"),
  workoutPlans: postOnly("/api/v1/workout-plans"),
  workoutAssignments: postOnly("/api/v1/workout-assignments"),
  trainingGoals: postOnly("/api/v1/training-goals"),
  measurements: postOnly("/api/v1/measurements"),
  progressRecords: postOnly("/api/v1/progress-records"),
  nutritionPlans: postOnly("/api/v1/nutrition-plans"),
  assessments: postOnly("/api/v1/assessments"),
  performanceRecords: postOnly("/api/v1/performance-records"),
  bodyCompositions: postOnly("/api/v1/body-compositions"),

  // Competitions
  competitions: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(`/api/v1/competitions${qs(params)}`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>("/api/v1/competitions", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
    update: (tenantId: string, id: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>(`/api/v1/competitions/${id}`, {
        tenantId,
        method: "PATCH",
        body: JSON.stringify(body),
      }),
  },
  competitionTeams: createOnly("/api/v1/competition-teams"),
  competitionGroups: createOnly("/api/v1/competition-groups"),
  competitionRegistrations: {
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>("/api/v1/competition-registrations", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
    confirm: (tenantId: string, id: string) =>
      action(tenantId, `/api/v1/competition-registrations/${id}/confirm`),
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(`/api/v1/competition-registrations${qs(params)}`, { tenantId }),
  },
  competitionMatches: createOnly("/api/v1/competition-matches"),
  competitionResults: createOnly("/api/v1/competition-results"),
  competitionRankings: listOnly("/api/v1/competition-rankings"),
  competitionMedals: createOnly("/api/v1/competition-medals"),
  competitionJudges: createOnly("/api/v1/competition-judges"),
  competitionCertificates: createOnly("/api/v1/competition-certificates"),
};
