/**
 * 문서 작성 서버 액션
 *
 * API Endpoints:
 * - GET /api/v1/reports/expense-estimate - 비용견적서 항목 조회
 * - GET /api/v1/employees - 직원 목록 (결재선/참조 선택용)
 * - POST /api/v1/approvals - 결재 문서 생성 (임시저장)
 * - POST /api/v1/approvals/{id}/submit - 결재 문서 상신
 */

'use server';


import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { cookies } from 'next/headers';
import { executeServerAction } from '@/lib/api/execute-server-action';
import { buildApiUrl } from '@/lib/api/query-params';
import type {
  ExpenseEstimateItem,
  ApprovalPerson,
  DocumentFormData,
  UploadedFile,
} from './types';

// ============================================
// API 응답 타입 정의
// ============================================

// 비용견적서 API 응답 타입
interface ExpenseEstimateApiItem {
  id: number;
  expected_payment_date: string;
  category: string;
  amount: number;
  vendor: string;
  account_info?: string;
  memo?: string;
}

interface ExpenseEstimateApiResponse {
  year_month: string;
  items: ExpenseEstimateApiItem[];
  total_expense: number;
  account_balance: number;
  final_difference: number;
}

// 직원 API 응답 타입 (TenantUserProfile 구조)
interface EmployeeApiData {
  id: number;              // TenantUserProfile.id
  user_id: number;         // User.id (결재선에 사용)
  position_key?: string;   // 직책 코드 (EXECUTIVE, DIRECTOR 등)
  user?: {
    id: number;
    name: string;
    email?: string;
  };
  department?: {
    id: number;
    name: string;
  };
}

// 결재 문서 생성 응답 타입
interface ApprovalCreateResponse {
  id: number;
  document_number: string;
  status: string;
}

// ============================================
// 헬퍼 함수
// ============================================

/**
 * 비용견적서 API 데이터 → 프론트엔드 데이터 변환
 */
function transformExpenseEstimateItem(item: ExpenseEstimateApiItem): ExpenseEstimateItem {
  return {
    id: String(item.id),
    checked: false,
    expectedPaymentDate: item.expected_payment_date,
    category: item.category,
    amount: item.amount,
    vendor: item.vendor,
    memo: item.account_info || item.memo || '',
  };
}

/**
 * 직책 코드를 한글 라벨로 변환 (직원 목록용)
 */
function getPositionLabelForEmployee(positionKey: string | null | undefined): string {
  if (!positionKey) return '';
  const labels: Record<string, string> = {
    'EXECUTIVE': '임원',
    'DIRECTOR': '부장',
    'MANAGER': '과장',
    'SENIOR': '대리',
    'STAFF': '사원',
    'INTERN': '인턴',
  };
  return labels[positionKey] ?? positionKey;
}

/**
 * 직원 API 데이터 → 결재자 데이터 변환
 * API는 TenantUserProfile 구조를 반환함
 */
function transformEmployee(employee: EmployeeApiData): ApprovalPerson {
  return {
    id: String(employee.user?.id || employee.user_id),  // User.id 사용 (결재선에 필요)
    name: employee.user?.name || '',
    position: getPositionLabelForEmployee(employee.position_key),
    department: employee.department?.name || '',
  };
}

// ============================================
// API 함수
// ============================================

/**
 * 파일 업로드
 * @param files 업로드할 파일 배열
 * @returns 업로드된 파일 정보 배열
 *
 * NOTE: 파일 업로드는 multipart/form-data가 필요하므로 serverFetch 대신 직접 fetch 사용
 */
export async function uploadFiles(files: File[]): Promise<{
  success: boolean;
  data?: UploadedFile[];
  error?: string;
}> {
  if (files.length === 0) {
    return { success: true, data: [] };
  }

  try {
    const cookieStore = await cookies();
    const token = cookieStore.get('access_token')?.value;

    const uploadedFiles: UploadedFile[] = [];

    // 파일을 하나씩 업로드 (멀티파트 폼)
    for (const file of files) {
      const formData = new FormData();
      formData.append('file', file);

      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/api/v1/files/upload`,
        {
          method: 'POST',
          headers: {
            'Authorization': token ? `Bearer ${token}` : '',
            'X-API-KEY': process.env.API_KEY || '',
            // Content-Type은 자동 설정됨 (multipart/form-data)
          },
          body: formData,
        }
      );

      if (!response.ok) {
        console.error('[DocumentCreateActions] File upload error:', response.status);
        return { success: false, error: `파일 업로드 실패: ${file.name}` };
      }

      const result = await response.json();
      if (result.success && result.data) {
        // API 응답 필드: id, display_name, file_path, file_size, mime_type
        uploadedFiles.push({
          id: result.data.id,
          name: result.data.display_name || file.name,
          url: `/api/proxy/files/${result.data.id}/download`,
          size: result.data.file_size,
          mime_type: result.data.mime_type,
        });
      }
    }

    return { success: true, data: uploadedFiles };
  } catch (error) {
    if (isNextRedirectError(error)) throw error;
    console.error('[DocumentCreateActions] uploadFiles error:', error);
    return { success: false, error: '파일 업로드 중 오류가 발생했습니다.' };
  }
}

/**
 * 비용견적서 항목 조회
 */
export async function getExpenseEstimateItems(yearMonth?: string): Promise<{
  items: ExpenseEstimateItem[];
  totalExpense: number;
  accountBalance: number;
  finalDifference: number;
} | null> {
  const result = await executeServerAction<ExpenseEstimateApiResponse>({
    url: buildApiUrl('/api/v1/reports/expense-estimate', { year_month: yearMonth }),
    errorMessage: '비용견적서 조회에 실패했습니다.',
  });
  if (!result.success || !result.data) return null;
  return {
    items: result.data.items.map(transformExpenseEstimateItem),
    totalExpense: result.data.total_expense,
    accountBalance: result.data.account_balance,
    finalDifference: result.data.final_difference,
  };
}

/**
 * 직원 목록 조회 (결재선/참조 선택용)
 */
export async function getEmployees(search?: string): Promise<ApprovalPerson[]> {
  const result = await executeServerAction<{ data: EmployeeApiData[] }>({
    url: buildApiUrl('/api/v1/employees', { per_page: 100, search }),
    errorMessage: '직원 목록 조회에 실패했습니다.',
  });
  if (!result.success || !result.data?.data) return [];
  return result.data.data.map(transformEmployee);
}

/**
 * 결재 문서 생성 (임시저장)
 */
export async function createApproval(formData: DocumentFormData): Promise<{
  success: boolean;
  data?: { id: number; documentNo: string };
  error?: string;
}> {
  // 새 첨부파일 업로드
  const newFiles = formData.proposalData?.attachments
    || formData.expenseReportData?.attachments
    || [];
  let uploadedFiles: UploadedFile[] = [];

  if (newFiles.length > 0) {
    const uploadResult = await uploadFiles(newFiles);
    if (!uploadResult.success) {
      return { success: false, error: uploadResult.error };
    }
    uploadedFiles = uploadResult.data || [];
  }

  const requestBody = {
    form_code: formData.basicInfo.formCode || formData.basicInfo.documentType,
    title: getDocumentTitle(formData),
    status: 'draft',
    is_urgent: formData.basicInfo.isUrgent || false,
    steps: [
      ...formData.approvalLine.map((person, index) => ({
        step_type: person.stepType || 'approval',
        step_order: index + 1,
        approver_id: parseInt(person.id),
      })),
      ...formData.references.map((person, index) => ({
        step_type: 'reference',
        step_order: formData.approvalLine.length + index + 1,
        approver_id: parseInt(person.id),
      })),
    ],
    content: getDocumentContent(formData, uploadedFiles),
    ...(getDocumentBody(formData) !== undefined && { body: getDocumentBody(formData) }),
  };

  const result = await executeServerAction<ApprovalCreateResponse>({
    url: buildApiUrl('/api/v1/approvals'),
    method: 'POST',
    body: requestBody,
    errorMessage: '문서 저장에 실패했습니다.',
  });
  if (!result.success || !result.data) return { success: false, error: result.error };
  return { success: true, data: { id: result.data.id, documentNo: result.data.document_number } };
}

/**
 * 결재 문서 상신
 */
export async function submitApproval(id: number): Promise<{
  success: boolean;
  error?: string;
}> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/approvals/${id}/submit`),
    method: 'POST',
    body: {},
    errorMessage: '문서 상신에 실패했습니다.',
  });
  return { success: result.success, error: result.error };
}

/**
 * 결재 문서 생성 및 상신 (한번에)
 */
export async function createAndSubmitApproval(formData: DocumentFormData): Promise<{
  success: boolean;
  data?: { id: number; documentNo: string };
  error?: string;
}> {
  try {
    // 1. 먼저 문서 생성
    const createResult = await createApproval(formData);
    if (!createResult.success || !createResult.data) {
      return createResult;
    }

    // 2. 상신
    const submitResult = await submitApproval(createResult.data.id);
    if (!submitResult.success) {
      return {
        success: false,
        error: submitResult.error || '문서 상신에 실패했습니다.',
      };
    }

    return {
      success: true,
      data: createResult.data,
    };
  } catch (error) {
    if (isNextRedirectError(error)) throw error;
    console.error('[DocumentCreateActions] createAndSubmitApproval error:', error);
    return {
      success: false,
      error: '서버 오류가 발생했습니다.',
    };
  }
}

/**
 * 결재 문서 조회 (수정 모드용)
 */
export async function getApprovalById(id: number): Promise<{
  success: boolean;
  data?: DocumentFormData;
  error?: string;
}> {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const result = await executeServerAction<any>({
    url: buildApiUrl(`/api/v1/approvals/${id}`),
    errorMessage: '문서 조회에 실패했습니다.',
  });
  if (!result.success || !result.data) return { success: false, error: result.error };
  return { success: true, data: transformApiToFormData(result.data) };
}

/**
 * 결재 문서 수정
 */
export async function updateApproval(id: number, formData: DocumentFormData): Promise<{
  success: boolean;
  data?: { id: number; documentNo: string };
  error?: string;
}> {
  // 새 첨부파일 업로드
  const newFiles = formData.proposalData?.attachments
    || formData.expenseReportData?.attachments
    || [];
  let uploadedFiles: UploadedFile[] = [];

  if (newFiles.length > 0) {
    const uploadResult = await uploadFiles(newFiles);
    if (!uploadResult.success) {
      return { success: false, error: uploadResult.error };
    }
    uploadedFiles = uploadResult.data || [];
  }

  const requestBody = {
    form_code: formData.basicInfo.formCode || formData.basicInfo.documentType,
    title: getDocumentTitle(formData),
    is_urgent: formData.basicInfo.isUrgent || false,
    steps: [
      ...formData.approvalLine.map((person, index) => ({
        step_type: person.stepType || 'approval',
        step_order: index + 1,
        approver_id: parseInt(person.id),
      })),
      ...formData.references.map((person, index) => ({
        step_type: 'reference',
        step_order: formData.approvalLine.length + index + 1,
        approver_id: parseInt(person.id),
      })),
    ],
    content: getDocumentContent(formData, uploadedFiles),
    ...(getDocumentBody(formData) !== undefined && { body: getDocumentBody(formData) }),
  };

  const result = await executeServerAction<ApprovalCreateResponse>({
    url: buildApiUrl(`/api/v1/approvals/${id}`),
    method: 'PATCH',
    body: requestBody,
    errorMessage: '문서 수정에 실패했습니다.',
  });
  if (!result.success || !result.data) return { success: false, error: result.error };
  return { success: true, data: { id: result.data.id, documentNo: result.data.document_number } };
}

/**
 * 결재 문서 수정 및 상신
 */
export async function updateAndSubmitApproval(id: number, formData: DocumentFormData): Promise<{
  success: boolean;
  data?: { id: number; documentNo: string };
  error?: string;
}> {
  try {
    // 1. 먼저 문서 수정
    const updateResult = await updateApproval(id, formData);
    if (!updateResult.success) {
      return updateResult;
    }

    // 2. 상신
    const submitResult = await submitApproval(id);
    if (!submitResult.success) {
      return {
        success: false,
        error: submitResult.error || '문서 상신에 실패했습니다.',
      };
    }

    return {
      success: true,
      data: updateResult.data,
    };
  } catch (error) {
    if (isNextRedirectError(error)) throw error;
    console.error('[DocumentCreateActions] updateAndSubmitApproval error:', error);
    return { success: false, error: '서버 오류가 발생했습니다.' };
  }
}

/**
 * 결재 문서 삭제
 */
export async function deleteApproval(id: number): Promise<{
  success: boolean;
  error?: string;
}> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/approvals/${id}`),
    method: 'DELETE',
    errorMessage: '문서 삭제에 실패했습니다.',
  });
  return { success: result.success, error: result.error };
}

// ============================================
// 내부 헬퍼 함수
// ============================================

/**
 * 문서 제목 생성
 */
function getDocumentTitle(formData: DocumentFormData): string {
  switch (formData.basicInfo.documentType) {
    case 'proposal':
      return formData.proposalData?.title || '품의서';
    case 'expenseReport':
      return `지출결의서 - ${formData.expenseReportData?.requestDate || ''}`;
    case 'expenseEstimate':
      return formData.expenseEstimateData?.title || '비용견적서';
    default: {
      // 전용 양식 중 title 필드가 있는 경우 활용
      const titleFromForm = formData.officialDocumentData?.title
        || formData.quotationData?.recipientName;
      if (titleFromForm) {
        return `${formData.basicInfo.formName || '문서'} - ${titleFromForm}`;
      }
      return formData.basicInfo.formName || '문서';
    }
  }
}

/**
 * 문서 본문(body) 추출 — body 필드를 사용하는 양식만 반환
 */
function getDocumentBody(formData: DocumentFormData): string | undefined {
  // 현재 body 필드를 사용하는 양식 없음 (비용견적서는 content로 전환됨)
  switch (formData.basicInfo.documentType) {
    default:
      return undefined;
  }
}

/**
 * 직책 코드를 한글 라벨로 변환
 */
function getPositionLabel(positionKey: string | null | undefined): string {
  if (!positionKey) return '';
  const labels: Record<string, string> = {
    'EXECUTIVE': '임원',
    'DIRECTOR': '부장',
    'MANAGER': '과장',
    'SENIOR': '대리',
    'STAFF': '사원',
    'INTERN': '인턴',
  };
  return labels[positionKey] ?? positionKey;
}

/**
 * API 응답을 프론트엔드 폼 데이터로 변환
 */
function transformApiToFormData(apiData: {
  id: number;
  document_number: string;
  form_code?: string;  // 이전 호환성
  form?: {             // 현재 API 구조
    id: number;
    name: string;
    code: string;
    category?: string;
    template?: Record<string, unknown>;
  };
  title: string;
  status: string;
  is_urgent?: boolean;
  content: Record<string, unknown>;
  body?: string;
  steps?: Array<{
    step_type: string;
    approver_id: number;
    approver?: {
      id: number;
      name: string;
      position?: string;
      department?: { name: string };
      tenant_profile?: {
        position_key?: string;
        display_name?: string;
        department?: { name: string };
      };
    };
  }>;
  created_at: string;
  requester?: {
    name: string;
  };
  drafter?: {
    id: number;
    name: string;
    tenant_profile?: {
      position_key?: string;
      display_name?: string;
      department?: { name: string };
    };
  };
}): DocumentFormData {
  // form.code를 우선 사용, 없으면 form_code (이전 호환성)
  const formCode = apiData.form?.code || apiData.form_code || 'proposal';
  // API code → 프론트엔드 documentType 매핑
  const FORM_CODE_MAP: Record<string, string> = {
    'proposal': 'proposal',
    'expense_report': 'expenseReport',
    'expenseReport': 'expenseReport',
    'expense_estimate': 'expenseEstimate',
    'expenseEstimate': 'expenseEstimate',
    'official_letter': 'officialDocument',
    'resignation': 'resignation',
    'leave_promotion_1st': 'leaveNotice1st',
    'leave_promotion_2nd': 'leaveNotice2nd',
    'delegation': 'powerOfAttorney',
    'board_minutes': 'boardMinutes',
    'employment_cert': 'employmentCert',
    'career_cert': 'careerCert',
    'appointment_cert': 'appointmentCert',
    'seal_usage': 'sealUsage',
    'quotation': 'quotation',
  };
  const documentType = FORM_CODE_MAP[formCode] || formCode;
  const content = apiData.content || {};

  // 결재선 및 참조자 분리
  const approvalLine: ApprovalPerson[] = [];
  const references: ApprovalPerson[] = [];

  if (apiData.steps) {
    for (const step of apiData.steps) {
      if (step.approver) {
        // tenantProfile에서 직책/부서 정보 추출 (우선), 없으면 기존 필드 사용
        const tenantProfile = step.approver.tenant_profile;
        const position = tenantProfile?.position_key
          ? getPositionLabel(tenantProfile.position_key)
          : (step.approver.position || '');
        const department = tenantProfile?.department?.name
          || step.approver.department?.name
          || '';

        const person: ApprovalPerson = {
          id: String(step.approver.id),
          name: step.approver.name,
          position,
          department,
          stepType: (step.step_type === 'agreement' ? 'agreement' : 'approval') as ApprovalPerson['stepType'],
        };

        // 'approval'과 'agreement' 모두 결재선에 포함
        if (step.step_type === 'approval' || step.step_type === 'agreement') {
          approvalLine.push(person);
        } else if (step.step_type === 'reference') {
          references.push(person);
        }
      }
    }
  }

  // 기본 정보 (drafter에서 tenantProfile 정보 추출)
  const drafterProfile = apiData.drafter?.tenant_profile;
  const basicInfo = {
    drafter: apiData.drafter?.name || apiData.requester?.name || '',
    drafterPosition: drafterProfile?.position_key
      ? getPositionLabel(drafterProfile.position_key)
      : '',
    drafterDepartment: drafterProfile?.department?.name || '',
    draftDate: apiData.created_at,
    documentNo: apiData.document_number,
    documentType,
    formId: apiData.form?.id,
    formCode: apiData.form?.code || formCode,
    formName: apiData.form?.name,
    formCategory: apiData.form?.category,
    isUrgent: apiData.is_urgent || false,
  };

  // 기존 업로드 파일 추출
  const existingFiles = (content.files as Array<{
    id: number;
    name: string;
    url?: string;
    size?: number;
    mime_type?: string;
  }>) || [];
  const uploadedFiles: UploadedFile[] = existingFiles.map(f => ({
    id: f.id,
    name: f.name,
    // URL이 없거나 상대 경로인 경우 다운로드 URL 생성
    url: f.url?.startsWith('http')
      ? f.url
      : `/api/proxy/files/${f.id}/download`,
    size: f.size,
    mime_type: f.mime_type,
  }));

  // 문서 유형별 데이터 변환
  let proposalData;
  let expenseReportData;
  let expenseEstimateData;

  if (documentType === 'proposal') {
    proposalData = {
      vendorId: (content.vendorId as string) || '',
      vendor: (content.vendor as string) || '',
      vendorPaymentDate: (content.vendorPaymentDate as string) || '',
      title: (content.title as string) || '',
      description: (content.description as string) || '',
      reason: (content.reason as string) || '',
      estimatedCost: (content.estimatedCost as number) || 0,
      attachments: [],
      uploadedFiles,
    };
  } else if (documentType === 'expenseReport') {
    const items = (content.items as Array<{
      id: string;
      description: string;
      amount: number;
      note?: string;
    }>) || [];

    expenseReportData = {
      requestDate: (content.requestDate as string) || '',
      paymentDate: (content.paymentDate as string) || '',
      items: items.map(item => ({
        id: item.id,
        description: item.description,
        amount: item.amount,
        note: item.note || '',
      })),
      cardId: (content.cardId as string) || '',
      totalAmount: (content.totalAmount as number) || 0,
      attachments: [],
      uploadedFiles,
    };
  } else if (documentType === 'expenseEstimate') {
    const items = (content.items as Array<{
      id: string;
      checked: boolean;
      expectedPaymentDate: string;
      category: string;
      amount: number;
      vendor: string;
      memo?: string;
    }>) || [];

    expenseEstimateData = {
      title: (apiData.title as string) || '',
      body: (apiData.body as string) || '',
      items: items.map((item, idx) => ({
        id: item.id || `restored-${idx}-${Date.now()}`,
        checked: item.checked || false,
        expectedPaymentDate: item.expectedPaymentDate,
        category: item.category,
        amount: item.amount,
        vendor: item.vendor,
        memo: item.memo || '',
      })),
      totalExpense: (content.totalExpense as number) || 0,
      accountBalance: (content.accountBalance as number) || 0,
      finalDifference: (content.finalDifference as number) || 0,
    };
  }

  // 12개 전용 양식 데이터: content에서 각 전용 폼 데이터로 매핑
  const DEDICATED_FORM_TYPES = [
    'officialDocument', 'resignation', 'employmentCert', 'careerCert',
    'appointmentCert', 'sealUsage', 'leaveNotice1st', 'leaveNotice2nd',
    'powerOfAttorney', 'boardMinutes', 'quotation',
  ];
  const isDedicatedBuiltin = ['proposal', 'expenseReport', 'expenseEstimate'].includes(documentType);
  const isDedicatedNew = DEDICATED_FORM_TYPES.includes(documentType);

  // 동적 폼 데이터: 전용 폼이 아닌 경우에만 content를 그대로 사용
  const dynamicFormData = (isDedicatedBuiltin || isDedicatedNew) ? undefined : content;

  // 전용 양식별 데이터 복원
  const dedicatedFormDataResult: Record<string, unknown> = {};
  if (isDedicatedNew && Object.keys(content).length > 0) {
    const key = `${documentType}Data`;
    dedicatedFormDataResult[key] = content;
  }

  return {
    basicInfo,
    approvalLine,
    references,
    proposalData,
    expenseReportData,
    expenseEstimateData,
    dynamicFormData,
    ...dedicatedFormDataResult,
  };
}

/**
 * 문서 내용 생성 (JSON)
 * @param formData 폼 데이터
 * @param uploadedFiles 새로 업로드된 파일 목록
 */
function getDocumentContent(
  formData: DocumentFormData,
  uploadedFiles: UploadedFile[] = []
): Record<string, unknown> {
  // 기존 업로드 파일 + 새로 업로드된 파일 합치기
  const existingFiles = formData.proposalData?.uploadedFiles
    || formData.expenseReportData?.uploadedFiles
    || [];
  const allFiles = [...existingFiles, ...uploadedFiles];

  switch (formData.basicInfo.documentType) {
    case 'proposal':
      return {
        vendorId: formData.proposalData?.vendorId,
        vendor: formData.proposalData?.vendor,
        vendorPaymentDate: formData.proposalData?.vendorPaymentDate,
        title: formData.proposalData?.title,
        description: formData.proposalData?.description,
        reason: formData.proposalData?.reason,
        estimatedCost: formData.proposalData?.estimatedCost,
        files: allFiles,
      };
    case 'expenseReport':
      return {
        requestDate: formData.expenseReportData?.requestDate,
        paymentDate: formData.expenseReportData?.paymentDate,
        items: formData.expenseReportData?.items,
        cardId: formData.expenseReportData?.cardId,
        totalAmount: formData.expenseReportData?.totalAmount,
        files: allFiles,
      };
    case 'expenseEstimate':
      return {
        items: formData.expenseEstimateData?.items?.map(item => ({
          expectedPaymentDate: item.expectedPaymentDate,
          category: item.category,
          amount: item.amount,
          vendor: item.vendor,
          memo: item.memo,
        })),
        totalExpense: formData.expenseEstimateData?.totalExpense,
        accountBalance: formData.expenseEstimateData?.accountBalance,
        finalDifference: formData.expenseEstimateData?.finalDifference,
      };
    default: {
      // 12개 전용 양식: 해당 폼 데이터를 content로 직렬화
      const dedicatedFormDataMap: Record<string, unknown> = {
        officialDocument: formData.officialDocumentData,
        resignation: formData.resignationData,
        employmentCert: formData.employmentCertData,
        careerCert: formData.careerCertData,
        appointmentCert: formData.appointmentCertData,
        sealUsage: formData.sealUsageData,
        leaveNotice1st: formData.leaveNotice1stData,
        leaveNotice2nd: formData.leaveNotice2ndData,
        powerOfAttorney: formData.powerOfAttorneyData,
        boardMinutes: formData.boardMinutesData,
        quotation: formData.quotationData,
      };
      const dedicatedData = dedicatedFormDataMap[formData.basicInfo.documentType];
      if (dedicatedData) return dedicatedData as Record<string, unknown>;
      // 동적 폼 데이터
      return formData.dynamicFormData || {};
    }
  }
}