<template>
    <v-card width="100%" :loading="loading.processing" :disabled="loading.processing || getAnnouncementByIdPending"
        :key="`form-key-${formKey}`">
        <v-toolbar>
            <v-row no-gutters class="fill-height px-6" align="center">
                <span class="font-weight-bold text-h5 text-capitalize">
                    {{ prop.mode }} Announcement
                </span>
            </v-row>
        </v-toolbar>
        <v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-6">
            <v-form ref="formRef" v-model="validForm" :disabled="loading.processing" @click="errorMessage = ''">
                <v-row no-gutters>
                    <v-col cols="12" class="font-weight-bold text-h6 mb-2">General Information</v-col>
                    <v-col cols="12">
                        <InputLabel title="Recipient(s)" />
                        <v-select v-model="bulletinForm.recipients" :items="recipientList" multiple item-value="value"
                            placeholder="Select recipients">
                            <template v-slot:prepend-item>
                                <v-list-item title="Select All" @click="handleSelectAll" class="">
                                    <template v-slot:prepend>
                                        <v-checkbox-btn :color="selectedSomeRecipients ? 'indigo-darken-4' : undefined"
                                            :indeterminate="selectedSomeRecipients && !selectedAllRecipients"
                                            :model-value="selectedAllRecipients"></v-checkbox-btn>
                                    </template>
                                </v-list-item>
                            </template>

                            <template v-slot:selection="{ item, index }">
                                <v-chip :text="item.title" class="py-2">
                                    <template #append>
                                        <v-btn icon="mdi-close" size="small" density="compact" color="transparent" flat
                                            class="ml-3 text-black" @mousedown.stop
                                            @click.stop="handleRemoveRecipient(item)" />
                                    </template>
                                </v-chip>
                            </template>
                        </v-select>
                    </v-col>
                    <v-col cols="12">
                        <InputLabel class="text-capitalize" title="Title" required />
                        <v-text-field v-model.trim="bulletinForm.title" density="compact" :rules="[requiredRule]" />
                    </v-col>
                    <v-col cols="12" class="my-4">
                        <InputLabel class="text-capitalize" title="Content" required />
                        <Editor v-model="bulletinForm.content" />
                    </v-col>

                    <v-col cols="12">
                        <v-checkbox v-model="bulletinForm.noExpiration" label="No Expiration" />
                    </v-col>

                    <v-col cols="12">
                        <InputLabel class="text-capitalize" title="Start Date" required />
                        <InputDateTimePicker v-model:utc="bulletinForm.startDate" :rules="[validStartDateRule]"/>
                    </v-col>

                    <v-col cols="12" v-if="!bulletinForm.noExpiration">
                        <InputLabel class="text-capitalize" title="End Date" required />
                        <InputDateTimePicker v-model:utc="bulletinForm.endDate" :rules="[validExpiryDateRule]" :min="today" />
                    </v-col>

                    <v-col cols="12">
                        <v-col cols="12" class="font-weight-bold text-h6">Attachments</v-col>
                        <v-col cols="12">
                            <v-btn text="Upload" class="text-capitalize" color="primary-button" variant="outlined"
                                min-width="150" @click="handleUpload" :loading="loading.uploading" />
                        </v-col>
                        <v-row no-gutters class="px-5">
                            <v-col cols="12">Videos ({{ videosArray.length }})</v-col>
                            <AttachmentList :list="videosArray" show-checkbox @set-preview="handleSetPreview"
                                @remove="handleRemoveFile" />

                            <v-col cols="12" class="mt-5">Photos ({{ photosArray.length }})</v-col>
                            <AttachmentList :list="photosArray" show-checkbox @set-preview="handleSetPreview"
                                @remove="handleRemoveFile" />

                            <v-col cols="12" class="mt-5">Files ({{ filesArray.length }})</v-col>
                            <AttachmentList :list="filesArray" show-checkbox @set-preview="handleSetPreview"
                                @remove="handleRemoveFile" />
                        </v-row>
                    </v-col>
                </v-row>
            </v-form>
        </v-card-text>

        <v-row no-gutters class="w-100" v-if="errorMessage">
            <p class="text-error w-100 text-center text-subtitle-2">{{ errorMessage }}</p>
        </v-row>
        <v-toolbar density="compact">
            <v-row no-gutters>
                <v-col cols="6">
                    <v-btn tile block variant="text" class="text-none" size="48" @click="close" text="Close" />
                </v-col>
                <v-col cols="6">
                    <v-btn tile block variant="flat" color="primary-button" class="text-none" size="48"
                        :text="prop.mode === 'add' ? 'Add Bulletin' : 'Save'"
                        :disabled="loading.processing || !validForm" @click="onSubmit" />
                </v-col>
            </v-row>
        </v-toolbar>
    </v-card>
</template>

<script setup lang="ts">
const today = computed(() => {
    const d = new Date()
    const yyyy = d.getFullYear()
    const mm = String(d.getMonth() + 1).padStart(2, '0')
    const dd = String(d.getDate()).padStart(2, '0')
    console.log('${yyyy}-${mm}-${dd}',`${yyyy}-${mm}-${dd}`)
    return `${yyyy}-${mm}-${dd}`
})

const prop = defineProps({
    siteId: {
        type: String,
        required: true
    },
    mode: {
        type: String as PropType<'edit' | 'add'>,
        default: "add"
    },
    activeId: {
        type: String,
        default: ""
    }
})

const { requiredRule } = useUtils()
const { addFile, urlToFile, getFileUrl } = useFile()
const { add, update, recipientList, getBulletinById } = useBulletin()

const bulletinForm = reactive<TCreateAnnouncementPayload>({
    recipients: [],
    title: "",
    content: "",
    site: prop.siteId,
    noExpiration: false,
    startDate: "",
    endDate: "",
    file: []
})

const emit = defineEmits(['close', 'done'])

const validForm = ref(false);
const formRef = ref<HTMLFormElement>()
const formKey = ref(0)
const errorMessage = ref('')

const rawFileArray = ref<{ file: File, _id: string, preview: boolean }[]>([])

const loading = reactive({
    uploading: false,
    processing: false
})




const photosArray = getByType('image/')
const videosArray = getByType('video/')
const filesArray = getByType('other')

function getByType(prefix: 'image/' | 'video/' | 'other') {
    return computed(() => {
        return rawFileArray.value.filter(x => {
            const type = x?.file?.type
            if (typeof type !== 'string') return false

            if (prefix === 'other') {
                return !type.startsWith('image/') && !type.startsWith('video/')
            }
            return type.startsWith(prefix)
        })
    })
}


const {
    data: getAnnouncementByIdReq,
    refresh: getAnnouncementByIdRefresh,
    pending: getAnnouncementByIdPending,
    error: getAnnouncementByIdError
} = await useLazyAsyncData(
    `get-announcements-${prop.activeId}`,
    () => {
        if(prop.mode === 'add') return Promise.resolve(null) // ignore when add mode
        const id = prop?.activeId
        if (!id) {
            throw new Error("Invalid activeId or mode. Cannot fetch announcement.")
        }
        return getBulletinById(id)
    },
    {
        watch: [() => prop.activeId],
    }
);

watch([getAnnouncementByIdReq, getAnnouncementByIdError], async ([newData, newError]) => {
    if (newData) {
        bulletinForm.title = newData?.title
        bulletinForm.content = newData?.content
        bulletinForm.noExpiration = newData?.noExpiration
        bulletinForm.startDate = newData?.startDate
        bulletinForm.endDate = newData?.endDate
        bulletinForm.file = newData?.file
        bulletinForm.recipients = newData?.recipients

        // mapped rawFileArray

        rawFileArray.value = await Promise.all(newData?.file?.map(async (item: TAnnouncementFile) => {
            const fileUrl = getFileUrl(item?._id)
            const file = await urlToFile(fileUrl, item?.name)
            return {
                file,
                _id: item?._id,
                preview: item.preview ?? false

            }
        }))

    }

    if (newError) {
        const errMessage = newError?.message
        console.error("Failed to load announcement:", errMessage)
        errorMessage.value = errMessage || ("Cannot fetch announcement" + newError)
    }
});

const allRecipientValues: TAnnouncementRecipients[] = recipientList.map(r => r.value)

const selectedAllRecipients = computed(() => {
    return bulletinForm.recipients.length === allRecipientValues.length &&
        bulletinForm.recipients.every((x) => allRecipientValues.includes(x))
})



const selectedSomeRecipients = computed(() => {
    return bulletinForm.recipients?.length > 0
})



function handleRemoveRecipient(item: any) {
    const recipientVal = item?.value
    const filtered = bulletinForm.recipients.filter(x => x !== recipientVal)
    bulletinForm.recipients = filtered
}

function handleSelectAll() {
    if (selectedAllRecipients.value) {
        bulletinForm.recipients = []
    } else {
        bulletinForm.recipients = allRecipientValues
    }
}


function validStartDateRule(value: string) {
    if (!value) {
        return 'Start Date is required';
    }

    return true;
}

function validExpiryDateRule() {
    const noExpiration = bulletinForm.noExpiration
    if (noExpiration) return true;
    const startDateISO = bulletinForm.startDate;
    const endDateISO = bulletinForm.endDate;
    if (!endDateISO) {
        return 'End Date is required';
    }

    if (endDateISO && startDateISO) {
        const expiry = new Date(endDateISO);
        const start = new Date(startDateISO as string);
        return expiry >= start || 'End date must be equal or later than start date';
    }
    return true;
}

watch(() => bulletinForm.noExpiration, (newVal) => {
    if (newVal === true) {
        setTimeout(() => {
            bulletinForm.endDate = ""
        }, 100)
    }
})


async function onSubmit() {
    errorMessage.value = ""
    await formRef.value?.validate()
    if (!validForm.value) {
        errorMessage.value = "Please complete required fields"
        return;
    }

    let payload: Partial<TCreateAnnouncementPayload> = {}
    if (prop.mode === 'add') {
        payload = { ...bulletinForm }
    } else if (prop.mode === 'edit') {
        const { site, ...rest } = bulletinForm
        payload = rest
    }

    try {
        loading.processing = true
        if (prop.mode === 'add') {
            await add(payload)
        } else if (prop.mode === 'edit') {
            const id = prop.activeId
            if (!id) throw new Error('Missing activeId prop')
            await update(prop.activeId, payload)
        } else {
            throw new Error('Missing mode prop!')
        }

        emit('done')

    } catch (error: any) {
        const err = error?.data?.message
        errorMessage.value = err || `Failed to ${prop.mode === 'add' ? 'add' : 'update'}. Please try again.`;

    } finally {
        loading.processing = false
    }
}

function close() {
    emit('close')
}

function handleUpload() {

    const input = document.createElement("input")
    input.type = "file"
    input.multiple = true

    input.onchange = async (event: Event) => {
        const target = event.target as HTMLInputElement
        const filesArray = target.files || []
        const MAX_SIZE = 25 * 1024 * 1024 // 25MB
        for (const file of filesArray) {
            loading.uploading = true

            if (file.size > MAX_SIZE) {
                errorMessage.value = `Skipping File "${file.name}", exceeds 25MB limit.`
                continue
            }

            try {
                const res = await addFile(file)
                const fileId = res?.id
                const fileName = file?.name || `file-${fileId}`
                if (fileId) {
                    rawFileArray.value.push({ file, _id: fileId, preview: false })
                    // bulletinForm.file.push({ name: fileName, preview: false, _id: fileId })
                }
            }
            catch (err: any) {
                console.error("Upload failed:", err)
                const message = err?.data?.message
                errorMessage.value = "Failed to upload image. Please try again."
            } finally {
                loading.uploading = false
            }

        }
    }
    input.click()
}

function handleSetPreview(fileId: string) {
    rawFileArray.value.forEach(item => {
        if (item._id !== fileId) {
            item.preview = false
        }
    })
}

function handleRemoveFile(fileId: string) {
    rawFileArray.value = rawFileArray.value.filter(item => item?._id !== fileId)
}

watch(rawFileArray, (newArr) => {
    bulletinForm.file = newArr.map(item => {
        return {
            _id: item?._id,
            name: item?.file?.name,
            preview: item?.preview,
        }
    })

}, { deep: true })


</script>

<style scoped></style>