<template>
  <v-row no-gutters class="mb-6">
    <v-col cols="12">
      <div class="text-subtitle-2 font-weight-bold mb-3">
        {{ title }}
        <span v-if="required" class="text-error">*</span>
      </div>

      <v-sheet
        border
        rounded="lg"
        class="pa-8 text-center upload-area"
        :class="{ 'upload-disabled': uploading }"
        style="cursor: pointer; transition: all 0.2s"
        @click="!uploading && (photoOptionsDialog = true)"
      >
        <v-icon
          :icon="uploading ? 'mdi-loading mdi-spin' : 'mdi-camera-plus-outline'"
          size="56"
          :color="uploading ? 'grey' : 'primary'"
          class="mb-3"
        />
        <div class="text-body-1 font-weight-medium mb-1">
          {{ uploading ? "Uploading Photo..." : "Add Photo" }}
        </div>
        <div class="text-caption text-medium-emphasis">
          {{ uploading ? "Please wait" : "Take a photo or upload from device" }}
        </div>
      </v-sheet>
    </v-col>
  </v-row>

  <v-row v-if="photos.length > 0" no-gutters>
    <v-col
      v-for="(photo, index) in photos"
      :key="index"
      cols="auto"
      class="pa-1"
    >
      <div class="position-relative" style="display: inline-block">
        <v-sheet
          rounded="sm"
          style="width: 88px; height: 64px; overflow: hidden; cursor: pointer"
          class="photo-thumb"
          @click="viewPhoto(photo)"
        >
          <v-img :src="photo" height="64" width="88" cover />
        </v-sheet>
        <v-btn
          icon="mdi-close"
          size="x-small"
          variant="tonal"
          color="error"
          class="delete-btn"
          @click.stop="removePhoto(index)"
          style="position: absolute; top: -8px; right: -8px"
        />
      </div>
    </v-col>
  </v-row>

  <v-dialog v-model="photoOptionsDialog" max-width="420">
    <v-card>
      <v-card-title class="d-flex align-center pa-4">
        <span class="text-h6 font-weight-bold">Add Photo</span>
        <v-spacer />
        <v-btn
          icon="mdi-close"
          variant="text"
          size="small"
          @click="photoOptionsDialog = false"
        />
      </v-card-title>

      <v-divider />

      <v-card-text class="pa-4">
        <v-list class="pa-0" bg-color="transparent">
          <v-list-item class="rounded-lg mb-2" @click="openCameraFromOptions">
            <template v-slot:prepend>
              <v-avatar color="primary" variant="tonal" size="48">
                <v-icon icon="mdi-camera" color="primary" />
              </v-avatar>
            </template>
            <v-list-item-title class="font-weight-medium mb-1">
              Take a Photo
            </v-list-item-title>
            <v-list-item-subtitle class="text-caption">
              Use device camera to capture an image
            </v-list-item-subtitle>
          </v-list-item>

          <v-list-item class="rounded-lg" @click="triggerFileInput">
            <template v-slot:prepend>
              <v-avatar color="primary" variant="tonal" size="48">
                <v-icon icon="mdi-upload" color="primary" />
              </v-avatar>
            </template>
            <v-list-item-title class="font-weight-medium mb-1">
              Upload a Photo
            </v-list-item-title>
            <v-list-item-subtitle class="text-caption">
              Select an image from your device
            </v-list-item-subtitle>
          </v-list-item>
        </v-list>
      </v-card-text>
    </v-card>
  </v-dialog>

  <v-dialog v-model="showCameraDialog" max-width="720">
    <v-card>
      <v-toolbar density="compact">
        <v-toolbar-title class="text-subtitle-1 font-weight-medium">
          Camera
        </v-toolbar-title>
        <v-spacer />
        <v-btn icon @click="closeCameraDialog">
          <v-icon>mdi-close</v-icon>
        </v-btn>
      </v-toolbar>
      <v-card-text>
        <div class="d-flex flex-column align-center">
          <div style="width: 100%; max-width: 640px">
            <video
              ref="videoRef"
              autoplay
              muted
              playsinline
              style="width: 100%; border-radius: 8px; background: #000"
            />
          </div>
          <canvas ref="canvasRef" style="display: none"></canvas>
          <div class="text-caption grey--text mt-2">
            Tip: Allow camera permissions to use this feature.
          </div>
        </div>
      </v-card-text>
      <v-card-actions>
        <v-btn
          text
          @click="closeCameraDialog"
          class="text-none font-weight-medium"
        >
          CANCEL
        </v-btn>
        <v-spacer />
        <v-btn
          block
          variant="flat"
          color="black"
          class="text-none font-weight-bold rounded-0"
          height="56"
          size="large"
          @click="capturePhoto"
        >
          <v-icon class="mr-2">mdi-camera</v-icon>
          CAPTURE
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>

  <input
    ref="fileInputRef"
    type="file"
    accept="image/*"
    style="display: none"
    @change="onFileSelected"
  />
</template>

<script setup lang="ts">
const props = defineProps({
  title: {
    type: String,
    default: "Photos (Optional)",
  },
  required: {
    type: Boolean,
    default: false,
  },
  modelValue: {
    type: Array as PropType<string[]>,
    default: () => [],
  },
  photoIds: {
    type: Array as PropType<string[]>,
    default: () => [],
  },
});

const emit = defineEmits(["update:modelValue", "update:photoIds", "error"]);

const photos = ref<string[]>([...props.modelValue]);
const photosIds = ref<string[]>([...props.photoIds]);
const photoOptionsDialog = ref(false);
const showCameraDialog = ref(false);
const videoRef = ref<HTMLVideoElement | null>(null);
const canvasRef = ref<HTMLCanvasElement | null>(null);
const fileInputRef = ref<HTMLInputElement | null>(null);
let mediaStream: MediaStream | null = null;
const uploading = ref(false);

const { addFile } = useFile();

function viewPhoto(photoData: string) {
  const link = document.createElement("a");
  link.href = photoData;
  link.target = "_blank";
  link.click();
}

watch(
  () => props.modelValue,
  (newVal) => {
    if (JSON.stringify(newVal) !== JSON.stringify(photos.value)) {
      photos.value = [...newVal];
    }
  },
);

watch(
  () => props.photoIds,
  (newVal) => {
    if (JSON.stringify(newVal) !== JSON.stringify(photosIds.value)) {
      photosIds.value = [...newVal];
    }
  },
);

watch(
  photos,
  (newVal) => {
    if (JSON.stringify(newVal) !== JSON.stringify(props.modelValue)) {
      emit("update:modelValue", newVal);
    }
  },
  { deep: true },
);

watch(
  photosIds,
  (newVal) => {
    if (JSON.stringify(newVal) !== JSON.stringify(props.photoIds)) {
      emit("update:photoIds", newVal);
    }
  },
  { deep: true },
);

function triggerFileInput() {
  photoOptionsDialog.value = false;
  fileInputRef.value?.click();
}

function onFileSelected(e: Event) {
  const input = e.target as HTMLInputElement;
  const file = input.files?.[0];
  if (!file) return;

  const reader = new FileReader();
  reader.onload = async () => {
    try {
      if (typeof reader.result === "string") {
        photos.value = [...photos.value, reader.result];
      }
      uploading.value = true;
      const uploadRes = await addFile(file);
      if (uploadRes?.id) {
        photosIds.value = [...photosIds.value, uploadRes.id];
      }
    } catch (err) {
      console.error("File upload error", err);
      emit("error", "Failed to upload image");

      if (photos.value.length > photosIds.value.length) {
        photos.value.pop();
      }
    } finally {
      uploading.value = false;
    }
  };
  reader.readAsDataURL(file);
  input.value = "";
}

async function openCameraFromOptions() {
  photoOptionsDialog.value = false;
  showCameraDialog.value = true;
  try {
    mediaStream = await navigator.mediaDevices.getUserMedia({
      video: true,
      audio: false,
    });
    if (videoRef.value) {
      videoRef.value.srcObject = mediaStream;
      await videoRef.value.play();
    }
  } catch (err) {
    console.error("Camera error", err);
    emit("error", "Unable to access camera");
    showCameraDialog.value = false;
  }
}

function capturePhoto() {
  if (!videoRef.value) return;

  const video = videoRef.value;
  const canvas = canvasRef.value || document.createElement("canvas");
  canvas.width = video.videoWidth || 640;
  canvas.height = video.videoHeight || 480;
  const ctx = canvas.getContext("2d");
  if (!ctx) return;

  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
  const data = canvas.toDataURL("image/jpeg", 0.9);
  photos.value = [...photos.value, data];

  // Convert to blob and upload
  canvas.toBlob(async (blob) => {
    if (!blob) {
      closeCameraDialog();
      return;
    }

    const file = new File([blob], `photo-${Date.now()}.jpg`, {
      type: "image/jpeg",
    });

    try {
      uploading.value = true;
      const uploadRes = await addFile(file);
      if (uploadRes?.id) {
        photosIds.value = [...photosIds.value, uploadRes.id];
      }
    } catch (err) {
      console.error("Capture upload error", err);
      emit("error", "Failed to upload captured image");
      // Remove the preview if upload failed
      if (photos.value.length > photosIds.value.length) {
        photos.value.pop();
      }
    } finally {
      uploading.value = false;
      closeCameraDialog();
    }
  }, "image/jpeg");
}

function closeCameraDialog() {
  showCameraDialog.value = false;
  if (mediaStream) {
    mediaStream.getTracks().forEach((t) => t.stop());
    mediaStream = null;
  }
  if (videoRef.value) {
    videoRef.value.pause();
    videoRef.value.srcObject = null;
  }
}

function removePhoto(index: number) {
  if (index < 0 || index >= photos.value.length) return;
  photos.value.splice(index, 1);
  if (photosIds.value && photosIds.value.length > index) {
    photosIds.value.splice(index, 1);
  }
}

onBeforeUnmount(() => {
  if (mediaStream) {
    mediaStream.getTracks().forEach((t) => t.stop());
    mediaStream = null;
  }
});
</script>

<style scoped>
.upload-area {
  &:hover:not(.upload-disabled) {
    border-color: rgb(var(--v-theme-primary)) !important;
    background-color: rgba(var(--v-theme-primary), 0.04);
  }
}

.upload-disabled {
  cursor: not-allowed !important;
  opacity: 0.6;
}

.photo-thumb {
  cursor: pointer;
  transition: transform 0.2s;
}

.photo-thumb:hover {
  transform: scale(1.05);
}

.delete-btn {
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  transition: all 0.2s;
}

.delete-btn:hover {
  transform: scale(1.1);
}
</style>
