<template>
  <div>
    <app-board-header
      :h2data="compData.title"
      v-if="!isEdit"
    ></app-board-header>

    <section
      class="bg-white dark:bg-gray-900 py-10 w-full min-h-[85vh] mt-20 mb-52"
    >
      <div class="mx-auto max-w-5xl w-full py-4 px-6 items-center">
        <div class="border-b border-gray-200 dark:border-gray-700 pb-8">
          <VeeForm @submit="handleUpload" v-slot="{ isSubmitting }">
            <!-- Title -->
            <div class="mb-3">
              <label
                for="title"
                class="inline-block mb-2 font-bold dark:text-gray-200"
                >제목</label
              >
              <VeeField
                name="title"
                type="text"
                rules="required|min:3"
                v-model="boardsData.title"
                class="block w-full py-1.5 px-3 border rounded text-gray-800 border-gray-300 focus:outline-none focus:border-indigo-500 dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 dark:focus:border-indigo-500"
                placeholder="제목을 입력하세요"
              />
              <VeeErrorMessage
                name="title"
                class="text-red-500 dark:text-red-400 text-sm mt-1"
              />
            </div>
            <!-- Subtitle -->
            <div class="mb-3">
              <label
                for="subtitle"
                class="inline-block mb-2 font-bold dark:text-gray-200"
                >부제목</label
              >
              <VeeField
                name="subtitle"
                type="text"
                rules="required|min:3"
                v-model="boardsData.subtitle"
                class="block w-full py-1.5 px-3 border rounded text-gray-800 border-gray-300 focus:outline-none focus:border-indigo-500 dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 dark:focus:border-indigo-500"
                placeholder="부제목목을 입력하세요"
              />
              <VeeErrorMessage
                name="subtitle"
                class="text-red-500 dark:text-red-400 text-sm mt-1"
              />
            </div>
            <!-- Author -->
            <div class="mb-3">
              <label
                for="author"
                class="inline-block mb-2 font-bold dark:text-gray-200"
                >클라이언트</label
              >
              <VeeField
                name="author"
                type="text"
                rules="required|min:3"
                v-model="boardsData.author"
                class="block w-full py-1.5 px-3 border rounded text-gray-800 border-gray-300 focus:outline-none focus:border-indigo-500 dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 dark:focus:border-indigo-500"
                placeholder="작성자를 입력하세요"
              />
              <VeeErrorMessage
                name="author"
                class="text-red-500 dark:text-red-400 text-sm mt-1"
              />
            </div>
            <!-- Announcement -->
            <div class="flex flex-wrap my-4">
              <div class="mb-3 mr-8">
                <Switch
                  id="announcement"
                  v-model="boardsData.announcement"
                  class="align-middle"
                  :class="[
                    boardsData.announcement
                      ? 'bg-indigo-600 dark:bg-indigo-500'
                      : 'bg-gray-200 dark:bg-gray-600', // Dark mode BG colors
                    'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900', // Dark focus ring offset
                  ]"
                >
                  <span class="sr-only">Use setting</span>
                  <span
                    aria-hidden="true"
                    :class="[
                      boardsData.announcement
                        ? 'translate-x-5'
                        : 'translate-x-0',
                      'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out', // Knob bg-white works for both modes
                    ]"
                  />
                </Switch>
                <label
                  for="announcement"
                  class="inline-block ml-2 align-middle dark:text-gray-200"
                  >공지글로 설정</label
                >>
              </div>

              <div class="mb-3">
                <Switch
                  v-model="boardsData.ishidden"
                  id="ishidden"
                  class="align-middle"
                  :class="[
                    boardsData.ishidden
                      ? 'bg-indigo-600 dark:bg-indigo-500'
                      : 'bg-gray-200 dark:bg-gray-600', // Dark mode BG colors
                    'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900', // Dark focus ring offset
                  ]"
                >
                  <span class="sr-only">Use setting</span>
                  <span
                    aria-hidden="true"
                    :class="[
                      boardsData.ishidden ? 'translate-x-5' : 'translate-x-0',
                      'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out', // Knob bg-white works for both modes
                    ]"
                  />
                </Switch>
                <label
                  for="ishidden"
                  class="inline-block ml-2 align-middle dark:text-gray-200"
                  >비밀글로 설정</label
                >>
              </div>
            </div>
            <!-- Upload Thumbnail -->
            <div class="mb-3 my-4">
              <label
                for="thumbnail"
                class="inline-block font-bold dark:text-gray-200"
                >이미지 (본문과 함께표시)</label
              >>

              <input
                ref="thumbnailInput"
                v-show="
                  !thumbnail.preview.value &&
                  !(
                    thumbnail.oldPreviewState.value && boardsData.thumbnail?.url
                  )
                "
                type="file"
                accept=".jpg, .jpeg, .png, .webp"
                @change="(e) => onThumbnailChange(e, thumbnail)"
                class="block w-full py-1.5 px-3 border border-gray-300 rounded mt-2 text-sm text-gray-900 dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700 cursor-pointer focus:outline-none dark:placeholder-gray-400 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100 dark:file:bg-indigo-700 dark:file:text-indigo-100 dark:hover:file:bg-indigo-600"
              />
              <div
                class="py-2"
                v-if="
                  thumbnail.preview.value ||
                  (thumbnail.oldPreviewState.value && boardsData.thumbnail?.url)
                "
              >
                <div
                  class="flex items-center md:flex text-sm mb-2 dark:text-gray-200"
                >
                  <div class="mx-5 font-medium">
                    {{ boardsData.thumbnail?.name }}
                  </div>
                  <button
                    type="button"
                    class="text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300 ml-4"
                    @click="onClearThumbnail"
                  >
                    >
                    <font-awesome-icon :icon="['fas', 'trash']" class="mr-1" />
                    삭제하기
                  </button>
                </div>
                <img
                  :src="thumbnail.preview.value || boardsData.thumbnail?.url"
                  class="max-w-full sm:max-w-md h-auto rounded shadow-md mb-2"
                />
              </div>
            </div>
            <!-- Upload Video -->
            <!-- <VideoUploader /> -->
            <!-- Upload Content -->
            <ClientOnly class="mb-3 space-y-2">
              <label for="description" class="font-bold dark:text-gray-200"
                >내용</label
              >
              <ckeditor
                v-if="editor && ckeditor"
                :editor="editor"
                v-model="boardsData.description"
                :config="editorConfig"
              ></ckeditor>
            </ClientOnly>

            <!-- Upload Files -->
            <ClientOnly>
              <FileUploadSlot
                v-for="(file, index) in uploadsData.files"
                :length="uploadsData.files.length"
                :key="index"
                :index="index"
                :file="file"
                :onChange="onPlainFileChange"
                :onClear="clearFileInput"
                :onAdd="() => addFileSlot(uploadsData.files)"
                @remove="removeFileSlot(uploadsData.files, index)"
              />
            </ClientOnly>

            <!-- Add File Button -->
            <button
              type="button"
              class="text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 underline mt-4 text-sm"
              @click="addFileSlot(uploadsData.files)"
            >
              > + 파일 추가
            </button>

            <!-- Submit Button -->
            <button
              type="submit"
              class="block w-full bg-indigo-600 text-white py-3 px-3 rounded transition hover:bg-indigo-700 mt-12 font-semibold dark:bg-indigo-500 dark:hover:bg-indigo-600 disabled:opacity-50 dark:disabled:opacity-60"
              :disabled="in_submission"
            >
              >
              <div
                v-if="show_alert"
                :class="[
                  alert_variant, // Ensure this variable contains dark: variants
                  'text-white text-center font-bold p-4 rounded mb-4',
                ]"
              >
                {{ alert_msg }}
              </div>

              <div v-show="!in_submission">
                {{ isEdit ? '수정하기' : '게시하기' }}
              </div>
              <div v-if="in_submission">
                <font-awesome-icon :icon="['fas', 'spinner']" spin />
              </div>
            </button>
          </VeeForm>
        </div>
      </div>
      <app-loading-overlay
        :isLoading="in_submission"
        :loadingMessage="loadingMessage"
      ></app-loading-overlay>
    </section>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, reactive, computed } from 'vue';
import AppBoardHeader from '@/components/boards/BoardHeader.vue';
import { useRouter } from 'vue-router';
import { fetchLatestDocumentNumber } from '@/utils/firebaseUtils';
import AppLoadingOverlay from '@/components/LoadingOverlay.vue';
import { Switch } from '@headlessui/vue';
import { editorConfig } from '@/utils/ckeditorUtils';
import {
  onPlainFileChange,
  resetFileSlots,
  getFilesFromUploads,
  createBoardsData,
  uploadFiles,
  onThumbnailChange,
  handleUpdateBoard,
  getDeleteFileIndexesFromUploads,
  clearFileInput,
  addFileSlot,
  removeFileSlot,
  clearThumbnailInput,
  createEmptyUploadFileData,
  getBoardDocRef,
} from '@/utils/boardUtils';
import FileUploadSlot from '@/components/boards/slots/FileUploadSlot.vue';
import VideoUploader from '@/components/boards/slots/VideoUploader.vue';
import {
  Form as VeeForm,
  Field as VeeField,
  ErrorMessage as VeeErrorMessage,
} from 'vee-validate';

import { syncBoardAndUploadsData } from '@/utils/boardUtils';

import { useUserStore } from '@/stores/user';
//types
import { useEditor } from '@/composables/useEditor';
import { UploadSettings } from '@/data/config';
import type {
  ProjectBoard,
  ThumbnailData,
  FileItem,
  UploadFileData,
  UploadsData,
} from '@/types';
import type { Ref } from 'vue';
const router = useRouter();
const props = defineProps({
  isEdit: { type: Boolean, default: false },
  board: { type: Object as PropType<ProjectBoard>, default: () => ({}) },
});
const emit = defineEmits(['update-success']);

const userStore = useUserStore();
const userId = computed(() => userStore.docId);
//customize
const { $firebase } = useNuxtApp();
const projectsCollection = $firebase.projectsCollection;
const currentCollection = projectsCollection;
const currentBoard = 'project';
const compData = {
  title: '프로젝트 | CMS',
};
//loading Message
const loadingMessage = 'Uploading! 잠시만 기다려주세요...';
const isUploading = ref(false);
//alert
const { show_alert, alert_variant, alert_msg, showAlert } = useAlert();

// Validation
const validateInput = (): boolean => {
  if (!boardsData.value.title.trim()) {
    showAlert('제목은 필수입니다!', 'bg-red-500', true);
    in_submission.value = false;
    return false;
  }
  return true;
};
//state
const in_submission = ref(false);
const isEdit = ref(props.isEdit ?? false);
const newBoard = ref(props.board);
const boardsData: Ref<ProjectBoard> = ref({
  docId: '',
  userId: '',
  title: '',
  created: '',
  boardState: { state: 'pending' },

  description: '',
  announcement: false,
  subtitle: '',
  author: '',
  displayDate: '',

  ishidden: false,
  boards_number: 0,

  thumbnail: { name: '', url: '' } as FileItem,
  files: [],
});
const thumbnailInput = ref<HTMLInputElement | null>(null);
const thumbnail: ThumbnailData = {
  input: ref(null),
  preview: ref(''),
  deleteTrigger: ref(false),
  oldPreviewState: ref(false),
  uploadState: ref(false),
  previewState: ref(false),
  displayedName: ref(''),
};
const files = reactive<UploadFileData[]>([]);

const uploadsData: UploadsData = {
  thumbnail,
  files,
};
//FOR EDIT, Write
const { editor, ckeditor, loadEditor } = useEditor();

const onClearThumbnail = () => {
  clearThumbnailInput(thumbnail, thumbnailInput.value, () => {
    boardsData.value.thumbnail = { name: '', url: '' };
  });
};
// firebase Upload
const handleUpload = async () => {
  in_submission.value = true;

  if (!validateInput()) {
    in_submission.value = false;
    return;
  }

  // ✅ Validate plain files (UploadFileData[])
  const rejectedFiles = uploadsData.files
    .map((fileData) => fileData?.input)
    .filter(
      (file) => file instanceof File && !UploadSettings.isValidFile(file)
    );

  if (rejectedFiles.length > 0) {
    const reason =
      rejectedFiles[0] instanceof File
        ? UploadSettings.getInvalidFileReasonKey(rejectedFiles[0])
        : null;
    const msg = UploadSettings.UploadErrorMessages[reason!];
    showAlert(msg ?? 'Invalid file', 'bg-red-500');
    in_submission.value = false;
    return;
  }

  try {
    const newBoardsNumber = await fetchLatestDocumentNumber(
      currentCollection,
      'boards_number'
    );

    let boardPayload = createBoardsData(boardsData.value, newBoardsNumber);

    // ✅ Collect valid files and thumbnail
    const { thumbnail, files } = getFilesFromUploads(uploadsData);

    if (isEdit.value) {
      if (!newBoard.value) {
        showAlert('기존 게시글 데이터를 찾을 수 없습니다.', 'bg-red-500');
        in_submission.value = false;
        return;
      }

      const oldFiles = newBoard.value.files ?? [];
      const oldThumbUrl = newBoard.value.thumbnail?.url ?? '';
      const deleteThumbnail = uploadsData.thumbnail.deleteTrigger.value;
      const deleteFileIndexes = getDeleteFileIndexesFromUploads(uploadsData);

      boardPayload = await uploadFiles({
        newBoardData: boardPayload,
        newThumbnail: thumbnail instanceof File ? thumbnail : null,
        newFiles: files,
        oldThumbnailUrl: oldThumbUrl,
        oldFiles,
        deleteThumbnail,
        deleteFileIndexes,
        currentBoard,
      });

      await handleUpdateBoard(boardPayload, currentCollection);
      showAlert('성공적으로 수정되었습니다', 'bg-green-800');
      emit('update-success');
    } else {
      const { docId: freshDocId } = getBoardDocRef(currentCollection);

      boardPayload = {
        ...boardPayload,
        docId: freshDocId,
        userId: userId.value,
      };
      boardPayload = await uploadFiles({
        newBoardData: boardPayload,
        newThumbnail: thumbnail,
        newFiles: files,
        currentBoard,
      });

      await handleUpdateBoard(boardPayload, currentCollection);
      showAlert('성공적으로 생성되었습니다', 'bg-green-800', true);
      router.push(`projects/${freshDocId}`);
    }
  } catch (error) {
    console.error('업로드 중 에러 발생:', error);
    showAlert('업로드 실패: 파일 또는 데이터 에러', 'bg-red-500');
  } finally {
    in_submission.value = false;
  }
};

onMounted(() => {
  loadEditor().catch((error) => {
    console.error('Error while initializing the editor:', error);
  });
  if (uploadsData.files.length === 0) {
    addFileSlot(uploadsData.files);
  }
  console.log('mounted', uploadsData);
});

watch(
  () => props.board,
  (newBoard) => {
    if (newBoard) {
      syncBoardAndUploadsData(
        newBoard,
        boardsData,
        uploadsData,
        createEmptyUploadFileData,
        resetFileSlots
      );
      console.log('newBoard', newBoard);
    }
  },
  { immediate: true }
);
</script>
<style>
.ck-editor__editable {
  min-height: 500px;
}
</style>
