import api from "@/lib/api/axios";
import type {
  AdminPackageListParams,
  AdminPackageListResponse,
  CreateWashPackageRequest,
  ProviderPackageListParams,
  ProviderPackageListResponse,
  ToggleProviderPackageRequest,
  ToggleProviderPackageResponse,
  UpdateWashPackageRequest,
  WashPackage,
} from "@/types/catalog";

/**
 * Service Catalog API (`/catalog`).
 *
 * Two guarded surfaces on one controller prefix: `/catalog/admin/*` is
 * `@Roles(ADMIN_SUPER, ADMIN_SUPPORT)` and owns the packages; `/catalog/provider/*`
 * is `@Roles(PROVIDER_OWNER, PROVIDER_MANAGER)` — note technicians are excluded —
 * and only opts in/out of them. The provider is resolved from the JWT, never
 * from a path param.
 *
 * The backend validates with `forbidNonWhitelisted: true`, so undefined params
 * are stripped before sending — an explicit `undefined` would serialize away
 * anyway, but an empty `search=""` would not, and the backend would treat it as
 * a real (always-matching) filter. Boolean filters are declared
 * `@IsBooleanString` backend-side, so they go over the wire as "true"/"false".
 */

// ─── Admin ───────────────────────────────────────────────────────────────────

export async function listAdminPackagesApi(
  params: AdminPackageListParams,
): Promise<AdminPackageListResponse> {
  const { data } = await api.get<AdminPackageListResponse>(
    "/catalog/admin/packages",
    {
      params: {
        ...(params.search?.trim() ? { search: params.search.trim() } : {}),
        ...(params.isActive !== undefined
          ? { isActive: String(params.isActive) }
          : {}),
        ...(params.page ? { page: params.page } : {}),
        ...(params.limit ? { limit: params.limit } : {}),
      },
    },
  );
  return data;
}

/** 409 when `name` collides with an existing package, 400 when max < min */
export async function createPackageApi(
  payload: CreateWashPackageRequest,
): Promise<WashPackage> {
  const { data } = await api.post<WashPackage>(
    "/catalog/admin/packages",
    payload,
  );
  return data;
}

/**
 * Partial update — omitted fields keep their stored value.
 *
 * Min/max are validated against the merged (payload + stored) pair, so sending
 * only `maxPrice` is still checked against the saved `minPrice`. Changing the
 * range does NOT clamp providers who already priced outside it.
 */
export async function updatePackageApi(
  id: string,
  payload: UpdateWashPackageRequest,
): Promise<WashPackage> {
  const { data } = await api.put<WashPackage>(
    `/catalog/admin/packages/${id}`,
    payload,
  );
  return data;
}

/**
 * Soft delete. The row survives with `isDeleted: true` and a mangled name, and
 * providers keep their `ProviderService` rows — the package simply disappears
 * from every listing.
 */
export async function deletePackageApi(id: string): Promise<void> {
  await api.delete(`/catalog/admin/packages/${id}`);
}

// ─── Provider ────────────────────────────────────────────────────────────────

export async function listProviderPackagesApi(
  params: ProviderPackageListParams,
): Promise<ProviderPackageListResponse> {
  const { data } = await api.get<ProviderPackageListResponse>(
    "/catalog/provider/packages",
    {
      params: {
        ...(params.search?.trim() ? { search: params.search.trim() } : {}),
        ...(params.isOffered !== undefined
          ? { isOffered: String(params.isOffered) }
          : {}),
        ...(params.page ? { page: params.page } : {}),
        ...(params.limit ? { limit: params.limit } : {}),
      },
    },
  );
  return data;
}

/**
 * Opt in/out of one catalog package, and set the price while opting in.
 *
 * This is also the price-UPDATE path — there is no dedicated endpoint, so
 * re-sending `optIn: true` with a new price upserts it. Opting out deletes the
 * row (and its price) outright, and returns 400 if bookings reference it.
 */
export async function toggleProviderPackageApi(
  packageId: string,
  payload: ToggleProviderPackageRequest,
): Promise<ToggleProviderPackageResponse> {
  const { data } = await api.post<ToggleProviderPackageResponse>(
    `/catalog/provider/packages/${packageId}/toggle`,
    payload,
  );
  return data;
}
