import 'server-only';
import {
  createMockDecorationItem,
  deleteMockDecorationItem,
  listAllDecorationItems,
  updateMockDecorationItem,
  type CreateDecorationItemInput,
  type UpdateDecorationItemInput,
} from '@/lib/data/mock/decoration-item-store';
import type { DecorationItem } from '@/lib/domain/decoration-item';
import type {
  DecorationItemQuery,
  DecorationItemSearchField,
} from '@/lib/domain/decoration-item-query';

/**
 * 꾸미기 아이템 Repository — **백엔드에 이 도메인의 API가 전혀 없다**(조회조차 없음, 사용자
 * 확정 사항 — edupay-backend 저장소에 대응 컨트롤러/서비스/매퍼가 없음을 확인했다). 그래서
 * admin-member-repository.ts처럼 "백엔드 응답 + mock 오버레이" 구조가 아니라, 이 계층 전체가
 * `lib/data/mock/decoration-item-store.ts` 하나로만 동작한다 — 조회·등록·수정·삭제 전부.
 *
 * **캐시 전략**: 실제 `fetch` 호출이 없어 `cache: 'no-store'`나 `next: { revalidate, tags }`
 * 같은 HTTP 캐시 옵션을 붙일 대상이 없다(CLAUDE.md §2.6이 요구하는 "명시"는 여기서는 "해당
 * 없음"을 명시하는 것으로 갈음한다). 대신 신선도는 두 가지로 보장한다:
 *   1. 호출부인 `page.tsx`가 `verifySession()`으로 쿠키를 읽어 이미 이 라우트를 동적 렌더링으로
 *      강제한다(요청마다 새로 실행).
 *   2. 각 Server Action이 저장 직후 `revalidatePath(DECORATION_ITEMS_PATH)`로 라우터 캐시를
 *      무효화한다.
 * admin-member-repository.ts와 동일한 신선도 보장 방식이다.
 *
 * 백엔드에 API가 생기면 이 파일의 "쓰기 경로" 세 함수와 조회 함수의 본문만 실제 `backendFetch`
 * 호출로 바꾸면 되고, 화면·Server Action은 그대로다.
 */

const SEARCH_VALUE_BY_FIELD: Record<
  DecorationItemSearchField,
  (item: DecorationItem) => string
> = {
  name: (item) => item.name,
  itemId: (item) => item.itemId,
};

function filterByKeyword(
  items: DecorationItem[],
  query: DecorationItemQuery
): DecorationItem[] {
  const keyword = query.keyword.trim().toLowerCase();
  if (!keyword) {
    return items;
  }

  const readValue = SEARCH_VALUE_BY_FIELD[query.searchField];
  return items.filter((item) => readValue(item).toLowerCase().includes(keyword));
}

/** 정렬순서 오름차순(시안 기본 정렬). 값이 같으면 아이템ID로 안정 정렬해 페이지를 넘나들 때
 *  순서가 흔들리지 않게 한다. */
function sortBySortOrder(items: DecorationItem[]): DecorationItem[] {
  return [...items].sort((a, b) =>
    a.sortOrder !== b.sortOrder
      ? a.sortOrder - b.sortOrder
      : a.itemId.localeCompare(b.itemId)
  );
}

export type DecorationItemPage = {
  items: DecorationItem[];
  /** 검색어까지 적용한 결과 건수 — 요약 문구·페이지네이션 기준. */
  totalCount: number;
  /**
   * 검색어와 무관하게 현재 유형(개별/셋트) 전체 등록 건수. 등록/수정 팝업의
   * "정렬순서 (총 등록 N개)" 힌트와 신규 등록 기본 정렬순서(맨 끝에 추가) 계산에 쓴다 — 검색
   * 결과가 아니라 그 유형에 실제로 존재하는 전체 개수여야 하므로 `totalCount`와 분리했다.
   */
  typeTotalCount: number;
};

/** 검색·유형·페이징이 적용된 꾸미기 아이템 목록을 조회한다. */
export async function fetchDecorationItems(
  query: DecorationItemQuery
): Promise<DecorationItemPage> {
  const byType = listAllDecorationItems().filter(
    (item) => item.itemType === query.itemType
  );
  const matched = sortBySortOrder(filterByKeyword(byType, query));
  const offset = (query.page - 1) * query.pageSize;

  return {
    items: matched.slice(offset, offset + query.pageSize),
    totalCount: matched.length,
    typeTotalCount: byType.length,
  };
}

/**
 * 아이템ID 중복 확인. 시안에 admins의 [중복확인] 같은 별도 버튼은 없지만, 아이템ID가 유일
 * 식별자이자 수정/삭제 대상 키라 등록 Server Action이 저장 직전에 반드시 확인한다
 * (`_actions.ts` 참조) — 화면에는 이 확인이 보이지 않고 실패 시 필드 오류로만 나타난다.
 */
export async function isDecorationItemIdTaken(itemId: string): Promise<boolean> {
  const normalized = itemId.trim().toLowerCase();
  return listAllDecorationItems().some(
    (item) => item.itemId.toLowerCase() === normalized
  );
}

/*
 * ─── 쓰기 경로 ────────────────────────────────────────────────────────────────
 * 백엔드에 이 도메인의 API가 전혀 없어 세 함수 모두 mock 저장소에 위임한다
 * (`lib/data/mock/decoration-item-store.ts`의 주석에 한계를 적어 두었다).
 */

export async function createDecorationItem(
  input: CreateDecorationItemInput
): Promise<void> {
  createMockDecorationItem(input);
}

export async function updateDecorationItem(
  itemId: string,
  input: UpdateDecorationItemInput
): Promise<void> {
  updateMockDecorationItem(itemId, input);
}

export async function deleteDecorationItem(itemId: string): Promise<void> {
  deleteMockDecorationItem(itemId);
}
