'use server';

import { revalidatePath } from 'next/cache';
import { verifySession } from '@/lib/auth/dal';
import { BackendRequestError } from '@/lib/http/backend-fetch';
import { uploadAttachment } from '@/lib/data/repositories/file-repository';
import {
  createSystemMenu,
  deleteSystemMenu,
  updateSystemMenu,
} from '@/lib/data/repositories/system-menu-repository';
import { FILE_MODULE } from '@/lib/domain/file-module';
import {
  validateSystemMenu,
  type SystemMenuFormState,
} from '@/lib/domain/system-menu-form';

const SYSTEM_MENUS_PATH = '/system/menus';
const SAVE_FAILED_MESSAGE = '저장하지 못했습니다. 잠시 후 다시 시도해 주세요.';

/** 백엔드가 돌려준 사유는 그대로 보여준다 — "최상위 메뉴가 없습니다"처럼 사용자가 알아야 할
 *  내용이고, 감추면 화면만 보고는 원인을 알 수 없다. */
function failureMessage(error: unknown, fallback: string): string {
  return error instanceof BackendRequestError ? error.message : fallback;
}
const DELETE_FAILED_MESSAGE = '삭제하지 못했습니다. 잠시 후 다시 시도해 주세요.';
const UPLOAD_FAILED_MESSAGE = '아이콘을 올리지 못했습니다. 잠시 후 다시 시도해 주세요.';

function readString(formData: FormData, key: string): string {
  const value = formData.get(key);
  return typeof value === 'string' ? value : '';
}

function parseFormNumber(formData: FormData, key: string): number {
  const trimmed = readString(formData, key).trim();
  return trimmed === '' ? NaN : Number(trimmed);
}

/**
 * 아이콘 칸의 결과 파일 아이디. 새 파일을 고르면 올려서 그 아이디를, 아니면 기존 아이디를
 * 쓴다. 비운 경우 빈 문자열을 보내 컬럼을 지운다.
 */
async function resolveIconId(
  formData: FormData,
  fileKey: string,
  currentKey: string
): Promise<string> {
  const picked = formData.get(fileKey);

  if (picked instanceof File && picked.size > 0) {
    return uploadAttachment(picked, FILE_MODULE.menuIcon.id);
  }

  return readString(formData, currentKey);
}

async function readValues(formData: FormData) {
  return {
    id: readString(formData, 'id'),
    parentId: readString(formData, 'parentId'),
    parentIdPath: readString(formData, 'parentIdPath'),
    name: readString(formData, 'name'),
    sortOrder: parseFormNumber(formData, 'sortOrder'),
    roleId: readString(formData, 'roleId'),
    isTopActive: readString(formData, 'isTopActive') === 'Y',
    url: readString(formData, 'url'),
    description: readString(formData, 'description'),
    largeIconId: await resolveIconId(formData, 'largeIcon', 'largeIconId'),
    smallIconId: await resolveIconId(formData, 'smallIcon', 'smallIconId'),
    isActive: readString(formData, 'isActive') === 'Y',
  };
}

export async function saveSystemMenuAction(
  _prevState: SystemMenuFormState,
  formData: FormData
): Promise<SystemMenuFormState> {
  await verifySession();

  let values;
  try {
    values = await readValues(formData);
  } catch {
    return { status: 'error', message: UPLOAD_FAILED_MESSAGE };
  }

  const validation = validateSystemMenu(values);
  if (!validation.ok) {
    return { status: 'error', errors: validation.errors };
  }

  try {
    if (validation.values.id) {
      await updateSystemMenu(validation.values);
    } else {
      await createSystemMenu(validation.values);
    }
  } catch (error) {
    return { status: 'error', message: failureMessage(error, SAVE_FAILED_MESSAGE) };
  }

  revalidatePath(SYSTEM_MENUS_PATH);
  return { status: 'success' };
}

export async function deleteSystemMenuAction(
  menuId: string
): Promise<{ status: 'success' } | { status: 'error'; message: string }> {
  await verifySession();

  try {
    await deleteSystemMenu(menuId);
  } catch (error) {
    return { status: 'error', message: failureMessage(error, DELETE_FAILED_MESSAGE) };
  }

  revalidatePath(SYSTEM_MENUS_PATH);
  return { status: 'success' };
}
