<template>
  <main class="container page-padding">
    <!-- <h1 class="mb-3">{{ pageTitle }}</h1> -->

    <VAlert v-if="error" type="error" :message="error" class="mb-3" :closable="false">
      <template #actions>
        <VButton variant="danger" size="sm" @click="fetchListsAndGroups">Retry</VButton>
      </template>
    </VAlert>

    <VCard v-else-if="lists.length === 0"
           variant="empty-state"
           empty-icon="clipboard"
           :empty-title="noListsMessage"
    >
      <template #default>
        <p v-if="!currentGroupId">Create a personal list or join a group to see shared lists.</p>
        <p v-else>This group doesn't have any lists yet.</p>
      </template>
      <template #empty-actions>
        <VButton variant="primary" class="mt-2" @click="showCreateModal = true" icon-left="plus">
          Create New List
        </VButton>
      </template>
    </VCard>

    <div v-else>
      <div class="neo-lists-grid">
        <div v-for="list in lists" :key="list.id" class="neo-list-card"
          :class="{ 'touch-active': touchActiveListId === list.id }" @click="navigateToList(list.id)"
          @touchstart="handleTouchStart(list.id)" @touchend="handleTouchEnd" @touchcancel="handleTouchEnd"
          :data-list-id="list.id">
          <div class="neo-list-header">{{ list.name }}</div>
          <div class="neo-list-desc">{{ list.description || 'No description' }}</div>
          <ul class="neo-item-list">
            <li v-for="item in list.items" :key="item.id" class="neo-list-item">
              <label class="neo-checkbox-label" @click.stop>
                <input type="checkbox" :checked="item.is_complete" @change="toggleItem(list, item)" />
                <span :class="{ 'neo-completed': item.is_complete }">{{ item.name }}</span>
              </label>
            </li>
            <li class="neo-list-item new-item-input">
              <label class="neo-checkbox-label">
                <input type="checkbox" disabled />
                <input type="text" class="neo-new-item-input" placeholder="Add new item..."
                  @keyup.enter="addNewItem(list, $event)" @blur="addNewItem(list, $event)" @click.stop />
              </label>
            </li>
          </ul>
        </div>
        <div class="neo-create-list-card" @click="showCreateModal = true">
          + Create a new list
        </div>
      </div>
    </div>

    <CreateListModal v-model="showCreateModal" :groups="availableGroupsForModal" @created="onListCreated" />
  </main>
</template>

<script setup lang="ts">
import { ref, onMounted, computed, watch, onUnmounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { apiClient, API_ENDPOINTS } from '@/config/api';
import CreateListModal from '@/components/CreateListModal.vue';
import { useStorage } from '@vueuse/core';
import VAlert from '@/components/valerie/VAlert.vue';
import VCard from '@/components/valerie/VCard.vue';
import VButton from '@/components/valerie/VButton.vue';
// VSpinner might not be needed here unless other parts use it directly

interface List {
  id: number;
  name: string;
  description?: string;
  is_complete: boolean;
  updated_at: string;
  created_by_id: number;
  group_id?: number | null;
  created_at: string;
  version: number;
  items: Item[];
}

interface Group {
  id: number;
  name: string;
}

interface Item {
  id: number;
  name: string;
  quantity?: string | number;
  is_complete: boolean;
  price?: number | null;
  version: number;
  updating?: boolean;
  updated_at: string;
}

const props = defineProps<{
  groupId?: number | string; // Prop for when ListsPage is embedded (e.g. in GroupDetailPage)
}>();

const route = useRoute();
const router = useRouter();

const loading = ref(false);
const error = ref<string | null>(null);
const lists = ref<(List & { items: Item[] })[]>([]);
const allFetchedGroups = ref<Group[]>([]);
const currentViewedGroup = ref<Group | null>(null);
const showCreateModal = ref(false);

const currentGroupId = computed<number | null>(() => {
  const idFromProp = props.groupId;
  const idFromRoute = route.params.groupId;
  if (idFromProp) {
    return typeof idFromProp === 'string' ? parseInt(idFromProp, 10) : idFromProp;
  }
  if (idFromRoute) {
    return parseInt(idFromRoute as string, 10);
  }
  return null;
});

const fetchCurrentViewGroupName = async () => {
  if (!currentGroupId.value) {
    currentViewedGroup.value = null;
    return;
  }
  // Try to find in already fetched groups first
  const found = allFetchedGroups.value.find(g => g.id === currentGroupId.value);
  if (found) {
    currentViewedGroup.value = found;
    return;
  }
  // If not found, fetch it specifically (might happen if navigating directly)
  try {
    const response = await apiClient.get(API_ENDPOINTS.GROUPS.BY_ID(String(currentGroupId.value)));
    currentViewedGroup.value = response.data as Group;
  } catch (err) {
    console.error(`Failed to fetch group name for ID ${currentGroupId.value}:`, err);
    currentViewedGroup.value = null; // Set to null if fetch fails
  }
};

const pageTitle = computed(() => {
  if (currentGroupId.value) {
    return currentViewedGroup.value
      ? `Lists for ${currentViewedGroup.value.name}`
      : `Lists for Group ${currentGroupId.value}`;
  }
  return 'My Lists';
});

const noListsMessage = computed(() => {
  if (currentGroupId.value) {
    return 'No lists found for this group.';
  }
  return 'You have no lists yet.';
});

const fetchAllAccessibleGroups = async () => {
  try {
    const response = await apiClient.get(API_ENDPOINTS.GROUPS.BASE);
    allFetchedGroups.value = (response.data as Group[]);
  } catch (err) {
    console.error('Failed to fetch groups for modal:', err);
    // Not critical for page load, modal might not show groups
  }
};

// Cache lists in localStorage
const cachedLists = useStorage<(List & { items: Item[] })[]>('cached-lists', []);
const cachedTimestamp = useStorage<number>('cached-lists-timestamp', 0);
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes in milliseconds

const loadCachedData = () => {
  const now = Date.now();
  if (cachedLists.value.length > 0 && (now - cachedTimestamp.value) < CACHE_DURATION) {
    lists.value = cachedLists.value;
  }
};

const fetchLists = async () => {
  try {
    const endpoint = currentGroupId.value
      ? API_ENDPOINTS.GROUPS.LISTS(String(currentGroupId.value))
      : API_ENDPOINTS.LISTS.BASE;
    const response = await apiClient.get(endpoint);
    lists.value = response.data as (List & { items: Item[] })[];

    // Update cache
    cachedLists.value = response.data;
    cachedTimestamp.value = Date.now();
  } catch (err: unknown) {
    error.value = err instanceof Error ? err.message : 'Failed to fetch lists.';
    console.error(error.value, err);
    // If we have cached data, keep showing it even if refresh failed
    if (cachedLists.value.length === 0) {
      lists.value = [];
    }
  }
};

const fetchListsAndGroups = async () => {
  await Promise.all([
    fetchLists(),
    fetchAllAccessibleGroups()
  ]);
  await fetchCurrentViewGroupName();
};

const availableGroupsForModal = computed(() => {
  return allFetchedGroups.value.map(group => ({
    label: group.name,
    value: group.id,
  }));
});

const getGroupName = (groupId?: number | null): string | undefined => {
  if (!groupId) return undefined;
  return allFetchedGroups.value.find(g => g.id === groupId)?.name;
}

const onListCreated = (newList: List & { items: Item[] }) => {
  lists.value = [...lists.value, newList];
  // Update cache
  cachedLists.value = lists.value;
  cachedTimestamp.value = Date.now();
};

const toggleItem = async (list: (List & { items: Item[] }), item: Item) => {
  const original = item.is_complete;
  item.is_complete = !item.is_complete;
  item.updating = true;
  try {
    await apiClient.put(
      API_ENDPOINTS.LISTS.ITEM(String(list.id), String(item.id)),
      {
        is_complete: item.is_complete,
        version: item.version,
        name: item.name,
        quantity: item.quantity,
        price: item.price
      }
    );
    item.version++;
  } catch (err) {
    item.is_complete = original;
    console.error('Failed to update item:', err);
  } finally {
    item.updating = false;
  }
};

const addNewItem = async (list: (List & { items: Item[] }), event: Event) => {
  const input = event.target as HTMLInputElement;
  const itemName = input.value.trim();

  if (!itemName) {
    input.value = '';
    return;
  }

  try {
    const response = await apiClient.post(API_ENDPOINTS.LISTS.ITEMS(String(list.id)), {
      name: itemName,
      is_complete: false,
      quantity: null,
      price: null
    });

    list.items.push(response.data as Item);
    input.value = '';
  } catch (err) {
    console.error('Failed to add new item:', err);
  }
};

const navigateToList = (listId: number) => {
  const selectedList = lists.value.find(l => l.id === listId);
  if (selectedList) {
    const listShell = {
      id: selectedList.id,
      name: selectedList.name,
      description: selectedList.description,
      group_id: selectedList.group_id,
    };
    sessionStorage.setItem('listDetailShell', JSON.stringify(listShell));
  }
  router.push({ name: 'ListDetail', params: { id: listId } });
};

// Add pre-fetching functionality using Intersection Observer
const prefetchListDetails = async (listId: number) => {
  try {
    const response = await apiClient.get(API_ENDPOINTS.LISTS.BY_ID(String(listId)));
    const fullListData = response.data;
    sessionStorage.setItem(`listDetailFull_${listId}`, JSON.stringify(fullListData));
  } catch (err) {
    console.warn('Pre-fetch failed:', err);
  }
};

// Setup Intersection Observer for pre-fetching
const setupIntersectionObserver = () => {
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const listId = entry.target.getAttribute('data-list-id');
        if (listId) {
          const cachedFullData = sessionStorage.getItem(`listDetailFull_${listId}`);
          if (!cachedFullData) {
            prefetchListDetails(Number(listId));
          }
        }
      }
    });
  }, {
    rootMargin: '50px 0px', // Start loading when card is 50px from viewport
    threshold: 0.1 // Trigger when at least 10% of the card is visible
  });

  // Observe all list cards
  document.querySelectorAll('.neo-list-card').forEach(card => {
    observer.observe(card);
  });

  return observer;
};

// Touch feedback state
const touchActiveListId = ref<number | null>(null);

const handleTouchStart = (listId: number) => {
  touchActiveListId.value = listId;
};

const handleTouchEnd = () => {
  touchActiveListId.value = null;
};

onMounted(() => {
  // Load cached data immediately
  loadCachedData();

  // Then fetch fresh data in background
  fetchListsAndGroups().then(() => {
    // Setup intersection observer after lists are loaded
    const observer = setupIntersectionObserver();

    // Cleanup observer on component unmount
    onUnmounted(() => {
      observer.disconnect();
    });
  });
});

// Watch for changes in groupId
watch(currentGroupId, () => {
  loadCachedData();
  fetchListsAndGroups();
});

</script>

<style scoped>
.page-padding {
  padding: 1rem;
  max-width: 1200px;
  margin: 0 auto;
}

.mb-3 {
  margin-bottom: 1.5rem;
}

/* Masonry grid for cards */
.neo-lists-grid {
  columns: 3 500px;
  column-gap: 2rem;
  margin-bottom: 2rem;
}

/* Card styles */
.neo-list-card,
.neo-create-list-card {
  break-inside: avoid;
  border-radius: 18px;
  box-shadow: 6px 6px 0 #111;
  width: 100%;
  margin: 0 0 2rem 0;
  background: var(--light);
  display: flex;
  flex-direction: column;
  /* padding: 2rem 2rem 1.5rem 2rem;
  padding: 2rem 2rem 1.5rem 2rem; */
  /* padding-inline: ; */
  cursor: pointer;
  /* transition: transform 0.1s ease-in-out, box-shadow 0.1s ease-in-out; */
  border: 3px solid #111;
  padding-inline: 1rem;
}

.neo-list-card:hover {
  /* transform: translateY(-3px); */
  box-shadow: 6px 9px 0 #111;
  /* padding: 2rem 2rem 1.5rem 2rem; */
  border: 3px solid #111;
}

.neo-list-header {
  padding-block-start: 1rem;
  font-weight: 900;
  font-size: 1.25rem;
  margin-bottom: 0.5rem;
  letter-spacing: 0.5px;
  text-transform: none;
}

.neo-list-desc {
  font-size: 1rem;
  color: #444;
  margin-bottom: 1.2rem;
  font-weight: 500;
}

.neo-item-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.neo-list-item {
  margin-bottom: 1.1rem;
  font-size: 1.1rem;
  font-weight: 700;
  display: flex;
  align-items: center;
}

.neo-checkbox-label {
  display: flex;
  align-items: center;
  gap: 0.7em;
  cursor: pointer;
}

.neo-checkbox-label input[type="checkbox"] {
  width: 1.2em;
  height: 1.2em;
  accent-color: #111;
  border: 2px solid #111;
  border-radius: 4px;
  margin-right: 0.5em;
}

.neo-completed {
  text-decoration: line-through;
  opacity: 0.5;
}

.neo-create-list-card {
  border: 3px dashed #111;
  background: var(--light);
  padding: 2.5rem 0;
  text-align: center;
  font-weight: 900;
  font-size: 1.1rem;
  color: #222;
  cursor: pointer;
  margin-top: 0;
  transition: background 0.1s;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 120px;
  margin-bottom: 2.5rem;
}

.neo-create-list-card:hover {
  background: #f0f0f0;
}

/* Responsive adjustments */
@media (max-width: 900px) {
  .neo-lists-grid {
    columns: 2 260px;
    column-gap: 1.2rem;
  }

  .neo-list-card,
  .neo-create-list-card {
    margin-bottom: 1.2rem;
    padding-left: 1rem;
    padding-right: 1rem;
  }
}

@media (max-width: 600px) {
  .page-padding {
    padding: 0.5rem;
  }

  .neo-lists-grid {
    columns: 1 280px;
    column-gap: 1rem;
  }

  .neo-list-card {
    margin-bottom: 1rem;
    padding: 1rem;
    font-size: 1rem;
    /* Optimize touch target size */
    min-height: 80px;
  }

  .neo-list-header {
    font-size: 1.1rem;
    margin-bottom: 0.3rem;
  }

  .neo-list-desc {
    font-size: 0.9rem;
    margin-bottom: 0.8rem;
  }

  /* Touch feedback */
  .neo-list-card.touch-active {
    transform: scale(0.98);
    transition: transform 0.1s ease-out;
  }

  /* Optimize checkbox size for touch */
  .neo-checkbox-label input[type="checkbox"] {
    width: 1.4em;
    height: 1.4em;
  }

  /* Optimize item spacing for touch */
  .neo-list-item {
    padding: 0.8rem 0;
    margin-bottom: 0.5rem;
  }
}

.neo-new-item-input {
  outline: none;
  border: none;
  margin-top: 0.5rem;
  padding: 0.5rem;
  background-color: var(--light) !important;
}

.neo-new-item-input input[type="text"] {
  border: none;
  outline: none;
  all: unset;
  width: 100%;
  font-size: 1.1rem;
  font-weight: 700;
  color: #444;
}

.neo-new-item-input input[type="text"]::placeholder {
  color: #999;
  font-weight: 500;
}

/* Add smooth transitions for all interactive elements */
.neo-list-card {
  transition: transform 0.1s ease-out, box-shadow 0.1s ease-out;
  -webkit-tap-highlight-color: transparent;
  /* Remove tap highlight on iOS */
}
</style>