<script setup lang="ts">
import { ref, watch, onMounted, computed } from 'vue'
import { getCachedImageUrl } from '../../common/imageCache'

const props = defineProps<{
  childId?: string | number
  assignFilter?: 'assignable' | 'assigned' | 'none'
  typeFilter?: 'good' | 'bad' | 'all'
  deletable?: boolean
  selectable?: boolean
}>()
const emit = defineEmits(['edit-task', 'delete-task'])

const tasks = ref<
  {
    id: string
    name: string
    points: number
    is_good: boolean
    image_id?: string | null
    image_url?: string | null
    assigned?: boolean
  }[]
>([])
const loading = ref(true)
const error = ref<string | null>(null)
const selectedTasks = ref<string[]>([])

const fetchTasks = async () => {
  loading.value = true
  error.value = null
  let url = ''
  if (props.childId) {
    url = `/api/child/${props.childId}/list-all-tasks`
    try {
      const resp = await fetch(url)
      if (!resp.ok) throw new Error(`HTTP ${resp.status}`)
      const data = await resp.json()
      const assigned = (data.assigned_tasks || []).map((task: any) => ({ ...task, assigned: true }))
      const assignable = (data.assignable_tasks || []).map((task: any) => ({
        ...task,
        assigned: false,
      }))
      let taskList: any[] = []
      if (props.assignFilter === 'assignable') {
        taskList = assignable
      } else if (props.assignFilter === 'assigned') {
        taskList = assigned
      } else if (props.assignFilter === 'none') {
        taskList = []
      } else {
        taskList = [...assigned, ...assignable]
      }
      // Fetch images for each task if image_id is present
      await Promise.all(
        taskList.map(async (task: any) => {
          if (task.image_id) {
            try {
              task.image_url = await getCachedImageUrl(task.image_id)
            } catch (e) {
              task.image_url = null
            }
          }
        }),
      )
      tasks.value = taskList

      // If selectable, pre-select assigned tasks
      if (props.selectable) {
        selectedTasks.value = assigned.map((task: any) => String(task.id))
      }
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to fetch tasks'
      tasks.value = []
      if (props.selectable) selectedTasks.value = []
    } finally {
      loading.value = false
    }
  } else {
    url = '/api/task/list'
    try {
      const resp = await fetch(url)
      if (!resp.ok) throw new Error(`HTTP ${resp.status}`)
      const data = await resp.json()
      const taskList = data.tasks || []
      await Promise.all(
        taskList.map(async (task: any) => {
          if (task.image_id) {
            try {
              task.image_url = await getCachedImageUrl(task.image_id)
            } catch (e) {
              task.image_url = null
            }
          }
        }),
      )
      tasks.value = taskList
      if (props.selectable) selectedTasks.value = []
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to fetch tasks'
      tasks.value = []
      if (props.selectable) selectedTasks.value = []
    } finally {
      loading.value = false
    }
  }
}

onMounted(fetchTasks)
watch(() => [props.childId, props.assignFilter], fetchTasks)

const handleEdit = (taskId: string) => {
  emit('edit-task', taskId)
}

const handleDelete = (taskId: string) => {
  emit('delete-task', taskId)
}

defineExpose({ refresh: fetchTasks, selectedTasks })

const ITEM_HEIGHT = 52 // px, adjust to match your .task-list-item + margin
const listHeight = computed(() => {
  // Add a little for padding, separators, etc.
  const n = tasks.value.length
  return `${Math.min(n * ITEM_HEIGHT + 8, window.innerHeight - 80)}px`
})

const filteredTasks = computed(() => {
  if (props.typeFilter === 'good') {
    return tasks.value.filter((t) => t.is_good)
  } else if (props.typeFilter === 'bad') {
    return tasks.value.filter((t) => !t.is_good)
  }
  return tasks.value
})
</script>

<template>
  <div class="task-listbox" :style="{ maxHeight: `min(${listHeight}, calc(100vh - 4.5rem))` }">
    <div v-if="loading" class="loading">Loading tasks...</div>
    <div v-else-if="error" class="error">{{ error }}</div>
    <div v-else-if="tasks.length === 0" class="empty">No tasks found.</div>
    <div v-else>
      <div v-for="(task, idx) in filteredTasks" :key="task.id">
        <div
          class="task-list-item"
          :class="{ good: task.is_good, bad: !task.is_good }"
          @click="handleEdit(task.id)"
        >
          <img v-if="task.image_url" :src="task.image_url" alt="Task" class="task-image" />
          <span class="task-name">{{ task.name }}</span>
          <span class="task-points">
            {{ task.is_good ? task.points : '-' + task.points }} pts
          </span>
          <!-- Add checkbox if selectable -->
          <input
            v-if="props.selectable"
            type="checkbox"
            class="task-checkbox"
            v-model="selectedTasks"
            :value="task.id"
            @click.stop
          />
          <button
            v-if="props.deletable"
            class="delete-btn"
            @click.stop="handleDelete(task.id)"
            aria-label="Delete task"
            type="button"
          >
            <svg width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
              <circle cx="10" cy="10" r="9" fill="#fff" stroke="#ef4444" stroke-width="2" />
              <path
                d="M7 7l6 6M13 7l-6 6"
                stroke="#ef4444"
                stroke-width="2"
                stroke-linecap="round"
              />
            </svg>
          </button>
        </div>
        <div v-if="idx < tasks.length - 1" class="task-separator"></div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.task-listbox {
  flex: 1 1 auto;
  width: auto;
  max-width: 480px;
  /* Subtract any header/nav height if needed, e.g. 4.5rem */
  max-height: calc(100vh - 4.5rem);
  overflow-y: auto;
  margin: 0.2rem 0 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  background: #fff5;
  padding: 0.2rem 0.2rem 0.2rem;
  border-radius: 12px;
}
.task-list-item {
  display: flex;
  align-items: center;
  border: 2px outset #38c172;
  border-radius: 8px;
  padding: 0.2rem 1rem;
  background: #f8fafc;
  font-size: 1.05rem;
  font-weight: 500;
  transition: border 0.18s;
  margin-bottom: 0.2rem;
  margin-left: 0.2rem;
  margin-right: 0.2rem;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.03);
  box-sizing: border-box;
}
.task-list-item.bad {
  border-color: #e53e3e;
  background: #fff5f5;
}
.task-list-item.good {
  border-color: #38c172;
  background: #f0fff4;
}
.task-image {
  width: 36px;
  height: 36px;
  object-fit: cover;
  border-radius: 8px;
  margin-right: 0.7rem;
  background: #eee;
  flex-shrink: 0;
}
.task-name {
  flex: 1;
  text-align: left;
}
.task-points {
  min-width: 60px;
  text-align: right;
  font-weight: 600;
}
.loading,
.error,
.empty {
  margin: 1.2rem 0;
  color: #888;
}
.error {
  color: #e53e3e;
}
.task-list-item:last-child {
  margin-bottom: 0;
}
.task-separator {
  height: 0px;
  background: #0000;
  margin: 0rem 0.2rem;
  border-radius: 0px;
}
.delete-btn {
  background: transparent;
  border: none;
  border-radius: 50%;
  padding: 0.15rem;
  margin-left: 0.7rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  transition:
    background 0.15s,
    box-shadow 0.15s;
  width: 2rem;
  height: 2rem;
  opacity: 0.92;
}
.delete-btn:hover {
  background: #ffeaea;
  box-shadow: 0 0 0 2px #ef444422;
  opacity: 1;
}
.delete-btn svg {
  display: block;
}
.task-checkbox {
  margin-left: 1rem;
  width: 1.2em;
  height: 1.2em;
  accent-color: #667eea;
  cursor: pointer;
}
</style>
