<template>
    <div class="container-xxl flex-grow-1 container-p-y">
        <div class="card">
            <div class="pb-4 rounded-top">
                <div class="container py-12 px-xl-10 px-4" style="padding-bottom: 0px !important">
                    <h3 class="text-center mb-2 mt-4">글 작성</h3>
                </div>
            </div>

            <div class="col-xl-12">
                <div class="card-body">
                    <FormInput
                        title="제목"
                        name="title"
                        :is-essential="true"
                        :is-alert="titleAlert"
                        v-model="title"
                        @update:alert="titleAlert = $event"
                        @input="validateTitle"
                    />

                    <!-- 카테고리 선택 -->
                    <div class="mb-4 d-flex align-items-center">
                        <label class="col-md-2 col-form-label">카테고리 <span class="text-danger">*</span></label>
                        <div class="d-flex flex-wrap align-items-center mt-3 ms-1">
                            <div v-for="(category, index) in categoryList" :key="index" class="form-check me-3">
                                <input
                                    class="form-check-input"
                                    type="radio"
                                    :id="`category-${index}`"
                                    :value="category.CMNCODVAL"
                                    v-model="categoryValue"
                                    @change="categoryAlert = false"
                                />
                                <label class="form-check-label" :for="`category-${index}`">
                                    {{ category.CMNCODNAM }}
                                </label>
                            </div>
                        </div>
                        <div class="invalid-feedback" :class="categoryAlert ? 'd-block' : 'd-none'">카테고리를 선택해주세요.</div>
                    </div>

                    <!-- 비밀번호 필드 (익명게시판 선택 시 활성화) -->
                    <div v-if="categoryValue === 300102" class="mb-4">
                        <FormInput
                            title="닉네임"
                            name="nickname"
                            :is-essential="true"
                            :is-alert="nicknameAlert"
                            v-model="nickname"
                            @update:alert="nicknameAlert = $event"
                            @input="validateNickname"
                            @keypress="noSpace"
                            :maxlength="6"
                        />
                        <FormInput
                            title="비밀번호"
                            name="pw"
                            type="password"
                            autocomplete="new-password"
                            :is-essential="true"
                            :is-alert="passwordAlert"
                            v-model="password"
                            @update:alert="passwordAlert = $event"
                            @input="validatePassword"
                        />
                    </div>

                    <!-- 첨부파일 업로드 -->
                    <FormFile
                        title="첨부파일"
                        name="files"
                        :is-alert="attachFilesAlert"
                        :key="autoIncrement"
                        @update:data="handleFileUpload"
                        @update:isValid="isFileValid = $event"
                    />

                    <!-- 실시간 반영된 파일 개수 표시 -->
                    <p class="text-muted mt-1">첨부파일: {{ fileCount }} / 5개</p>
                    <p v-if="fileError" class="text-danger">{{ fileError }}</p>

                    <ul class="list-group mt-2" v-if="attachFiles.length">
                        <li
                            v-for="(file, index) in attachFiles"
                            :key="index"
                            class="list-group-item d-flex justify-content-between align-items-center"
                        >
                            {{ file.name }}
                            <button class="close-btn" @click="removeFile(index)">✖</button>
                        </li>
                    </ul>

                    <!-- 내용 입력 (에디터) -->
                    <div class="mb-4">
                        <label class="col-md-2 col-form-label"> 내용 <span class="text-danger">*</span> </label>
                        <div class="col-md-12">
                            <QEditor
                                @update:data="content = $event"
                                @update:uploadedImgList="handleUpdateEditorImg"
                                @update:deleteImgIndexList="handleDeleteEditorImg"
                            />
                        </div>
                        <div class="invalid-feedback mt-1" :class="contentAlert ? 'd-block' : 'd-none'">내용을 입력해주세요.</div>
                    </div>

                    <div class="mb-4 d-flex justify-content-end">
                        <BackButton @click="goList" />
                        <SaveButton @click="write" :isEnabled="isFileValid" />
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script setup>
    import { ref, onMounted, getCurrentInstance, watch, computed } from 'vue';
    import QEditor from '@c/editor/QEditor.vue';
    import FormInput from '@c/input/FormInput.vue';
    import FormFile from '@c/input/FormFile.vue';
    import SaveButton from '@c/button/SaveBtn.vue';
    import BackButton from '@c/button/BackBtn.vue';
    import { useToastStore } from '@s/toastStore';
    import router from '@/router';
    import axios from '@api';

    const toastStore = useToastStore();
    const categoryList = ref([]);
    const title = ref('');
    const nickname = ref('');
    const password = ref('');
    const categoryValue = ref(null);
    const content = ref({ ops: [] });
    const isFileValid = ref(true);

    const titleAlert = ref(false);
    const nicknameAlert = ref(false);
    const passwordAlert = ref(false);
    const contentAlert = ref(false);
    const categoryAlert = ref(false);
    const attachFilesAlert = ref(false);

    const attachFiles = ref([]);
    const maxFiles = 5;
    const maxSize = 10 * 1024 * 1024;
    const fileError = ref('');
    const editorUploadedImgList = ref([]);
    const editorDeleteImgList = ref([]);

    const noSpace = (e) => {
        if (e.key === ' ') e.preventDefault();
    };

    const fetchCategories = async () => {
        const response = await axios.get('board/categories');
        categoryList.value = response.data.data;
        const freeCategory = categoryList.value.find(category => category.CMNCODNAM === '자유');
        if (freeCategory) {
            categoryValue.value = freeCategory.CMNCODVAL;
        }
    };

    const autoIncrement = ref(0);

    onMounted(() => {
        fetchCategories();
    });

    const fileCount = computed(() => attachFiles.value.length);

    const handleUpdateEditorImg = item => {
        editorUploadedImgList.value = item;
    };

    const handleDeleteEditorImg = item => {
        editorDeleteImgList.value = item;
    };

    const handleFileUpload = files => {
        const validFiles = files.filter(file => file.size <= maxSize);
        if (files.some(file => file.size > maxSize)) {
            fileError.value = '파일 크기가 10MB를 초과할 수 없습니다.';
            return;
        }
        if (attachFiles.value.length + validFiles.length > maxFiles) {
            fileError.value = `최대 ${maxFiles}개의 파일만 업로드할 수 있습니다.`;
            return;
        }

        fileError.value = '';
        attachFiles.value = [...attachFiles.value, ...validFiles].slice(0, maxFiles);

        autoIncrement.value++;
    };

    const removeFile = index => {
        attachFiles.value.splice(index, 1);
        if (attachFiles.value.length <= maxFiles) {
            fileError.value = '';
        }
        autoIncrement.value++;
    };

    watch(attachFiles, () => {
        isFileValid.value = attachFiles.value.length <= maxFiles;
    });

    const validateTitle = () => {
        titleAlert.value = title.value.trim().length === 0;
    };

    const validateNickname = () => {
        if (categoryValue.value === 300102) {
            nickname.value = nickname.value.replace(/\s/g, ''); // 공백 제거
            nicknameAlert.value = nickname.value.length === 0 ;
        } else {
            nicknameAlert.value = false;
        }
    };

    const validatePassword = () => {
        if (categoryValue.value === 300102) {
            password.value = password.value.replace(/\s/g, ''); // 공백 제거
            passwordAlert.value = password.value.length === 0;
        } else {
            passwordAlert.value = false;
        }
    };

    const validateContent = () => {
        if (!content.value?.ops?.length) {
            contentAlert.value = true;
            return;
        }

        // 이미지 포함 여부 확인
        const hasImage = content.value.ops.some(op => op.insert && typeof op.insert === 'object' && op.insert.image);
        // 텍스트 포함 여부 확인
        const hasText = content.value.ops.some(op => typeof op.insert === 'string' && op.insert.trim().length > 0);

        // 텍스트 또는 이미지가 하나라도 있으면 유효한 내용
        contentAlert.value = !(hasText || hasImage);
    };

    /** 글쓰기 */
    const write = async () => {
        validateTitle();
        validateNickname();
        validatePassword();
        validateContent();
        categoryAlert.value = categoryValue.value == null;

        if (
            titleAlert.value ||
            nicknameAlert.value ||
            passwordAlert.value ||
            contentAlert.value ||
            categoryAlert.value ||
            !isFileValid.value
        ) {
            return;
        }

        try {
            const boardData = {
                LOCBRDTTL: title.value,
                LOCBRDCON: JSON.stringify(content.value), // Delta 포맷을 JSON으로 변환
                LOCBRDNIC: categoryValue.value === 300102 ? nickname.value : null,
                LOCBRDPWD: categoryValue.value === 300102 ? password.value : null,
                LOCBRDTYP: categoryValue.value,
            };

            // 에디터에 업로드 된 이미지 인덱스 목록
            if (editorUploadedImgList.value && editorUploadedImgList.value.length > 0) {
                boardData.editorUploadedImgList = [...editorUploadedImgList.value];
            }

            // 삭제할 에디터 이미지 인덱스
            if (editorDeleteImgList.value && editorDeleteImgList.value.length > 0) {
                boardData.editorDeleteImgList = [...editorDeleteImgList.value];
            }

            const { data: boardResponse } = await axios.post('board', boardData);
            const boardId = boardResponse.data;
            // 첨부파일 업로드 (비동기 병렬 처리)
            if (attachFiles.value && attachFiles.value.length > 0) {
                await Promise.all(
                    attachFiles.value.map(async file => {
                        const formData = new FormData();
                        const fileNameWithoutExt = file.name.replace(/\.[^/.]+$/, '');

                        formData.append('CMNBRDSEQ', boardId);
                        formData.append('CMNFLEORG', fileNameWithoutExt);
                        formData.append('CMNFLEEXT', file.name.split('.').pop());
                        formData.append('CMNFLESIZ', file.size);
                        formData.append('file', file); // 📌 실제 파일 추가

                        await axios.post(`board/${boardId}/attachments`, formData, { isFormData: true });
                    }),
                );
            }

            toastStore.onToast('게시물이 작성되었습니다.', 's');
            goList();
        } catch (error) {
            toastStore.onToast('게시물 작성 중 오류가 발생했습니다.', 'e');
        }
    };

    /** 목록으로 이동 */
    const goList = () => {
        router.push('/board');
    };

    /** `content` 변경 감지하여 자동 유효성 검사 실행 */
    watch(content, () => {
        validateContent();
    });
</script>
