<script setup>
import { Button } from '@/components/ui/button/index.js'
import { useForm } from 'vee-validate'
import { FormControl, FormField, FormItem, FormLabel } from '@/components/ui/form/index.js'
import { Textarea } from '@/components/ui/textarea/index.js'
import { Input } from '@/components/ui/input/index.js'
import { Label } from '@/components/ui/label/index.js'
import { toTypedSchema } from '@vee-validate/zod'
import { z } from 'zod'
import { onMounted, onUnmounted, ref } from 'vue'
import { AlertCircle, ArrowLeft, ArrowRight, CircleCheckBig, CirclePlus, RefreshCcw } from 'lucide-vue-next'
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious
} from '@/components/ui/carousel/index.js'
import { Card, CardContent } from '@/components/ui/card/index.js'
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert/index.js'
import { useAuthStore } from '@/stores/auth.js'
import { API_BASE_URL, S3_BUCKET, S3_ENDPOINT } from '@/config.js'

const authStore = useAuthStore();

const formSchema = toTypedSchema(z.object({
  description: z.string().min(1),
  latitude: z.number(),
  longitude: z.number(),
  city: z.string().min(1),
  country: z.string().min(1)
}))
const form = useForm({
  validationSchema: formSchema
})

const formContainer = ref(null)
const latitudeInput = ref(null)
const longitudeInput = ref(null)
const selectedFiles = ref([])

const formStatus = ref({
  sending: false,
  sent: false,
  error: false,
  errorMsg: ''
})

const onSubmit = form.handleSubmit(async (values) => {
  if (!authStore.isAuth)
    return
  console.log('Envoi du post...')
  if (selectedFiles.value.length === 0)
    return
  formContainer.value.classList.add('hidden')
  formStatus.value.sending = true

  const assets = []
  for (const file of selectedFiles.value) {
    console.log('Contact API asset')
    const response = await fetch(API_BASE_URL + '/admin/assets', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        "X-admin-token": authStore.adminToken
      },
      body: JSON.stringify({ filename: file.file.name })
    })

    if (!response.ok) {
      console.log('Contact API asset failed: ' + response.statusText + '\n\n' + response.body)
      formStatus.value.sending = false
      formStatus.value.error = true
      formStatus.value.errorMsg = 'Une erreur est survenue à la préparation de l\'envoi d\'un média : ' + response.statusText
      formContainer.value.classList.remove('invisible')
      return
    }
    const responseBody = await response.json()
    const mediaUploadFormData = new FormData()
    for (const [key, value] of Object.entries(responseBody.formData)) {
      mediaUploadFormData.append(key, value)
    }
    mediaUploadFormData.append('key', '${filename}')
    mediaUploadFormData.append('Content-Type', file.file.type)
    mediaUploadFormData.append('file', file.file, responseBody.filename)

    console.log('Envoi image sur s3')
    const s3Response = await fetch(`${S3_ENDPOINT}/${S3_BUCKET}/`, {
      method: 'POST',
      body: mediaUploadFormData
    })
    if (!s3Response.ok) {
      console.log('Envoi media S3 failed: ' + s3Response.statusText + '\n\n' + s3Response.body)
      formStatus.value.sending = false
      formStatus.value.error = true
      formStatus.value.errorMsg = 'Une erreur est survenue pendant l\'envoi d\'un média : ' + s3Response.statusText
      formContainer.value.classList.remove('invisible')
      return
    }

    assets.push(responseBody.id)
  }

  const response = await fetch(API_BASE_URL + '/admin/posts', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      "X-admin-token": authStore.adminToken
    },
    body: JSON.stringify({
      description: values.description,
      latitude: values.latitude,
      longitude: values.longitude,
      city: values.city,
      country: values.country,
      assets: assets
    })
  })
  if (!response.ok) {
    console.log('POST post API failed: ' + response.statusText + '\n\n' + response.body)
    formStatus.value.sending = false
    formStatus.value.error = true
    formStatus.value.errorMsg = 'Une erreur est survenue lors de l\'envoi du poste : ' + response.statusText
    formContainer.value.classList.remove('hidden')
    return
  }

  formStatus.value.sending = false
  formStatus.value.sent = true
})

let geoWatchId = null

onMounted(() => {
  geoWatchId = navigator.geolocation.watchPosition((position) => {
    console.log(position)
    form.setFieldValue('latitude', position.coords.latitude)
    form.setFieldValue('longitude', position.coords.longitude)
  })
})

onUnmounted(() => {
  if (geoWatchId != null) {
    navigator.geolocation.clearWatch(geoWatchId)
  }
})

function onFilesSelected(event) {
  console.log(event.target.files)
  selectedFiles.value = []
  for (const file of event.target.files) {
    selectedFiles.value.push({ displayUrl: URL.createObjectURL(file), file: file })
  }
}

function mediaReorder(index, diff) {
  const tmp = selectedFiles.value[index]
  selectedFiles.value[index] = selectedFiles.value[index + diff]
  selectedFiles.value[index + diff] = tmp
}

</script>

<template>
  <div class="grid grid-cols-3 grid-rows-1 mt-20 w-full justify-center items-center gap-4">
    <div class="col-span-3 col-start-1 lg:col-span-1 lg:col-start-2 mx-5 lg:mx-0">
      <h1 class="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl mb-6">
        Ajouter un post
      </h1>
      <RouterLink to="/admin">
        <Button class="mb-6">
          <ArrowLeft class="mr-2" />
          Retour
        </Button>
      </RouterLink>
      <Alert variant="destructive" class="mb-6" v-if="formStatus.error">
        <AlertCircle class="w-4 h-4"></AlertCircle>
        <AlertTitle>Erreur...</AlertTitle>
        <AlertDescription>{{ formStatus.errorMsg }}</AlertDescription>
      </Alert>
      <Alert class="mb-6" v-if="formStatus.sent">
        <CircleCheckBig class="w-4 h-4"></CircleCheckBig>
        <AlertTitle>Post créé !</AlertTitle>
      </Alert>
      <p v-if="formStatus.sending">Sending...</p>
      <div id="form-container" ref="formContainer">
        <form id="post-form" class="space-y-6" @submit="onSubmit">
          <FormField v-slot="{ componentField }" name="description">
            <FormItem>
              <FormLabel>Description</FormLabel>
              <FormControl>
                <Textarea v-bind="componentField"></Textarea>
              </FormControl>
            </FormItem>
          </FormField>
          <div class="grid grid-cols-2 gap-4">
            <FormField ref="latitudeInput" v-slot="{ componentField }" name="latitude">
              <FormItem>
                <FormLabel>Latitude</FormLabel>
                <FormControl>
                  <Input disabled v-bind="componentField"></Input>
                </FormControl>
              </FormItem>
            </FormField>
            <FormField ref="longitudeInput" v-slot="{ componentField }" name="longitude">
              <FormItem>
                <FormLabel>Longitude</FormLabel>
                <FormControl>
                  <Input disabled v-bind="componentField"></Input>
                </FormControl>
              </FormItem>
            </FormField>
          </div>
          <div class="grid grid-cols-9 gap-4">
            <FormField v-slot="{ componentField }" name="city">
              <FormItem class="col-span-4">
                <FormLabel>Ville</FormLabel>
                <FormControl>
                  <Input v-bind="componentField"></Input>
                </FormControl>
              </FormItem>
            </FormField>
            <FormField v-slot="{ componentField }" name="country">
              <FormItem class="col-span-4">
                <FormLabel>Pays</FormLabel>
                <FormControl>
                  <Input v-bind="componentField"></Input>
                </FormControl>
              </FormItem>
            </FormField>
            <Button class="place-self-end">
              <RefreshCcw />
            </Button>
          </div>
        </form>
        <form id="assets-form" class="mt-6">
          <Label for="medias">Medias</Label>
          <Input id="medias" type="file" accept="image/*,video/*" multiple @change="onFilesSelected" />
        </form>
        <Carousel
          class="w-full mt-10"
          :opts="{
          align: 'start',
        }"
          v-if="selectedFiles.length > 0"
        >
          <CarouselContent>
            <CarouselItem v-for="(file, index) in selectedFiles" :key="index" class="md:basis-1/2 lg:basis-1/3">
              <div class="flex flex-col">
                <Card>
                  <CardContent class="flex aspect-square items-center justify-center p-6">
                    <img :src="file.displayUrl" v-if="file.file.type.startsWith('image/')" />
                  </CardContent>
                </Card>
                <div class="grid grid-cols-2 justify-items-center mt-2">
                  <Button v-if="index > 0" @click="mediaReorder(index, -1)">
                    <ArrowLeft />
                  </Button>
                  <div v-else></div>
                  <Button v-if="index < selectedFiles.length - 1" @click="mediaReorder(index, 1)">
                    <ArrowRight />
                  </Button>
                </div>
              </div>
            </CarouselItem>
          </CarouselContent>
          <CarouselPrevious />
          <CarouselNext />
        </Carousel>
        <Button class="mt-6 w-full" type="submit" form="post-form">
          <CirclePlus />
        </Button>
      </div>
    </div>
  </div>
</template>

<style scoped>
</style>
