import 'server-only';
import { getSessionAccessToken } from '@/lib/auth/dal';
import { BackendRequestError, backendFetch } from '@/lib/http/backend-fetch';
import type { AdminNotification } from '@/lib/domain/notification';

/**
 * 관리자 알림 Repository.
 *
 * ```
 * GET /api/v1/common/ntcn/list       로그인한 사용자의 알림 전체(등록일시 최신순)
 * PUT /api/v1/common/ntcn/{ntcnSn}   읽음 처리
 * ```
 *
 * 관리자 전용(`mngr`)이 아니라 공통 경로다 — 토큰의 주인이 누구인지로 대상이 갈리고,
 * 인가는 "로그인했으면 통과"라 관리자 토큰으로도 조회된다(SecurityConfig 확인함).
 *
 * 지금 적재되는 알림은 「학습자가 1:1문의를 등록했다」 하나다(`CmmBbsServiceImpl`이 등록 시
 * 관리자 전원에게 한 건씩 넣는다).
 *
 * ⚠️ 읽음 처리(`PUT /{ntcnSn}`)는 **아직 아무것도 바꾸지 못한다** — 백엔드 컨트롤러가
 * 경로변수 `ntcnSn`도 `readYn`도 VO에 담지 않아 `WHERE ntcn_sn = NULL`로 어느 행도 갱신되지
 * 않고 200만 돌아온다(보고함). 호출은 규약대로 붙여 두었으니 백엔드가 두 줄
 * (`setNtcnSn(ntcnSn)`·`setReadYn("Y")`)을 채우면 프론트 수정 없이 동작한다.
 *
 * 페이징이 없다. 목록 SQL에 LIMIT이 없어 전체가 온다 — 알림이 쌓이면 백엔드에 상한을
 * 요청해야 한다.
 */

const NOTIFICATION_PATH = '/api/v1/common/ntcn';
const NOTIFICATION_LIST_PATH = `${NOTIFICATION_PATH}/list`;

function isRecord(value: unknown): value is Record<string, unknown> {
  return value !== null && typeof value === 'object';
}

function readString(source: Record<string, unknown>, key: string): string {
  const value = source[key];
  return typeof value === 'string' ? value : '';
}

function toNotification(raw: unknown): AdminNotification | null {
  if (!isRecord(raw)) {
    return null;
  }

  // `ntcnSn`은 숫자로 올 수도 있다 — 키로만 쓰므로 문자열로 맞춘다.
  const rawId = raw.ntcnSn;
  const id =
    typeof rawId === 'string'
      ? rawId
      : typeof rawId === 'number'
        ? String(rawId)
        : '';
  if (!id) {
    return null;
  }

  return {
    id,
    title: readString(raw, 'ntcnSj'),
    content: readString(raw, 'ntcnCn'),
    isRead: readString(raw, 'readYn') === 'Y',
  };
}

/**
 * 로그인한 관리자의 알림을 가져온다.
 *
 * **실패해도 던지지 않는다.** 헤더는 모든 화면에 붙어 있어, 알림 조회가 안 된다고 화면
 * 전체가 죽으면 안 된다. 못 가져오면 빈 목록으로 둔다.
 */
export async function fetchNotifications(): Promise<AdminNotification[]> {
  const accessToken = await getSessionAccessToken();
  if (!accessToken) {
    return [];
  }

  try {
    const result = await backendFetch<unknown>(NOTIFICATION_LIST_PATH, {
      method: 'GET',
      accessToken,
      cache: 'no-store',
      canHaveNullData: true,
    });

    if (!result.ok) {
      throw new BackendRequestError(result);
    }

    return Array.isArray(result.data)
      ? result.data
          .map(toNotification)
          .filter((item): item is AdminNotification => item !== null)
      : [];
  } catch {
    return [];
  }
}

export async function markNotificationRead(id: string): Promise<void> {
  const accessToken = await getSessionAccessToken();

  const result = await backendFetch<null>(
    `${NOTIFICATION_PATH}/${encodeURIComponent(id)}`,
    {
      method: 'PUT',
      accessToken: accessToken ?? undefined,
      cache: 'no-store',
      canHaveNullData: true,
    }
  );

  if (!result.ok) {
    throw new BackendRequestError(result);
  }
}
