<template>
  <main class="neo-container page-padding">
    <div v-if="pageInitialLoad && !list && !error" class="text-center py-10">
      <VSpinner :label="$t('listDetailPage.loading.list')" size="lg" />
    </div>

    <VAlert v-else-if="error && !list" type="error" :message="error" class="mb-4">
      <template #actions>
        <VButton @click="fetchListDetails">{{ $t('listDetailPage.retryButton') }}</VButton>
      </template>
    </VAlert>

    <template v-else-if="list">
      <!-- Items List Section -->
      <VCard v-if="itemsAreLoading" class="py-10 text-center mt-4">
        <VSpinner :label="$t('listDetailPage.loading.items')" size="lg" />
      </VCard>
      <VCard v-else-if="!itemsAreLoading && list.items.length === 0" variant="empty-state" empty-icon="clipboard"
        :empty-title="$t('listDetailPage.items.emptyState.title')"
        :empty-message="$t('listDetailPage.items.emptyState.message')" class="mt-4" />
      <div v-else class="neo-item-list-container">
        <!-- Integrated Header -->
        <div class="neo-list-card-header">
          <div class="neo-list-header-main">
            <div class="neo-list-title-group">
              <VHeading :level="1" :text="list.name" class="neo-title" />


              <div class="item-badge ml-2" :class="list.group_id ? 'accent' : 'settled'">
                {{ list.group_id ? $t('listDetailPage.badges.groupList', { groupName: getGroupName(list.group_id) }) :
                  $t('listDetailPage.badges.personalList') }}
              </div>
            </div>

            <div class="neo-header-actions">
              <button class="btn btn-sm btn-primary" @click="showCostSummaryDialog = true" :disabled="!isOnline"
                icon-left="clipboard" size="sm">{{
                  $t('listDetailPage.buttons.costSummary') }}
              </button>
              <button class="btn btn-sm btn-primary" @click="openOcrDialog" :disabled="!isOnline" icon-left="plus"
                size="sm">{{
                  $t('listDetailPage.buttons.addViaOcr') }}
              </button>
              <button class="btn btn-sm btn-primary" @click="showCreateExpenseForm = true" :disabled="!isOnline"
                icon-left="plus" size="sm">
                {{ $t('listDetailPage.expensesSection.addExpenseButton') }}
              </button>
            </div>
          </div>
          <p v-if="list.description" class="neo-description-internal">{{ list.description }}</p>
          <div class="supermarkt-mode-toggle">
            <label>
              Supermarkt Mode
              <VToggleSwitch v-model="supermarktMode" />
            </label>
          </div>
          <VProgressBar v-if="supermarktMode" :value="itemCompletionProgress" class="mt-4" />
        </div>
        <!-- End Integrated Header -->

        <div v-for="group in groupedItems" :key="group.categoryName" class="category-group"
          :class="{ 'highlight': supermarktMode && group.items.some(i => i.is_complete) }">
          <h3 v-if="group.items.length" class="category-header">{{ group.categoryName }}</h3>
          <draggable v-model="group.items" item-key="id" handle=".drag-handle" @end="handleDragEnd"
            :disabled="!isOnline" class="neo-item-list">
            <template #item="{ element: item }">
              <li class="neo-list-item"
                :class="{ 'bg-gray-100 opacity-70': item.is_complete, 'item-pending-sync': isItemPendingSync(item) }">
                <div class="neo-item-content">
                  <!-- Drag Handle -->
                  <div class="drag-handle" v-if="isOnline">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
                      stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                      <circle cx="9" cy="12" r="1"></circle>
                      <circle cx="9" cy="5" r="1"></circle>
                      <circle cx="9" cy="19" r="1"></circle>
                      <circle cx="15" cy="12" r="1"></circle>
                      <circle cx="15" cy="5" r="1"></circle>
                      <circle cx="15" cy="19" r="1"></circle>
                    </svg>
                  </div>
                  <!-- Content when NOT editing -->
                  <template v-if="!item.isEditing">
                    <label class="neo-checkbox-label" @click.stop>
                      <input type="checkbox" :checked="item.is_complete" @change="handleCheckboxChange(item, $event)" />
                      <div class="checkbox-content">
                        <span class="checkbox-text-span"
                          :class="{ 'neo-completed-static': item.is_complete && !item.updating }">
                          {{ item.name }}
                        </span>
                        <span v-if="item.quantity" class="text-sm text-gray-500 ml-1">× {{ item.quantity }}</span>
                        <div v-if="item.is_complete" class="neo-price-input">
                          <VInput type="number" :model-value="item.priceInput || ''"
                            @update:modelValue="item.priceInput = $event"
                            :placeholder="$t('listDetailPage.items.pricePlaceholder')" size="sm" class="w-24"
                            step="0.01" @blur="updateItemPrice(item)"
                            @keydown.enter.prevent="($event.target as HTMLInputElement).blur()" />
                        </div>
                      </div>
                    </label>
                    <div class="neo-item-actions">
                      <button class="neo-icon-button neo-edit-button" @click.stop="startItemEdit(item)"
                        :aria-label="$t('listDetailPage.items.editItemAriaLabel')">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
                          stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                          <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
                          <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
                        </svg>
                      </button>
                      <button class="neo-icon-button neo-delete-button" @click.stop="deleteItem(item)"
                        :disabled="item.deleting" :aria-label="$t('listDetailPage.items.deleteItemAriaLabel')">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
                          stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                          <path d="M3 6h18"></path>
                          <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2">
                          </path>
                          <line x1="10" y1="11" x2="10" y2="17"></line>
                          <line x1="14" y1="11" x2="14" y2="17"></line>
                        </svg>
                      </button>
                    </div>
                  </template>
                  <!-- Content WHEN editing -->
                  <template v-else>
                    <div class="inline-edit-form flex-grow flex items-center gap-2">
                      <VInput type="text" :model-value="item.editName ?? ''" @update:modelValue="item.editName = $event"
                        required class="flex-grow" size="sm" @keydown.enter.prevent="saveItemEdit(item)"
                        @keydown.esc.prevent="cancelItemEdit(item)" />
                      <VInput type="number" :model-value="item.editQuantity || ''"
                        @update:modelValue="item.editQuantity = $event" min="1" class="w-20" size="sm"
                        @keydown.enter.prevent="saveItemEdit(item)" @keydown.esc.prevent="cancelItemEdit(item)" />
                      <VSelect :model-value="item.editCategoryId" @update:modelValue="item.editCategoryId = $event"
                        :options="categoryOptions" placeholder="Category" class="w-40" size="sm" />
                    </div>
                    <div class="neo-item-actions">
                      <button class="neo-icon-button neo-save-button" @click.stop="saveItemEdit(item)"
                        :aria-label="$t('listDetailPage.buttons.saveChanges')">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
                          stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                          <path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path>
                          <polyline points="17 21 17 13 7 13 7 21"></polyline>
                          <polyline points="7 3 7 8 15 8"></polyline>
                        </svg>
                      </button>
                      <button class="neo-icon-button neo-cancel-button" @click.stop="cancelItemEdit(item)"
                        :aria-label="$t('listDetailPage.buttons.cancel')">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
                          stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                          <circle cx="12" cy="12" r="10"></circle>
                          <line x1="15" y1="9" x2="9" y2="15"></line>
                          <line x1="9" y1="9" x2="15" y2="15"></line>
                        </svg>
                      </button>
                      <button class="neo-icon-button neo-delete-button" @click.stop="deleteItem(item)"
                        :disabled="item.deleting" :aria-label="$t('listDetailPage.items.deleteItemAriaLabel')">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
                          stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                          <path d="M3 6h18"></path>
                          <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2">
                          </path>
                          <line x1="10" y1="11" x2="10" y2="17"></line>
                          <line x1="14" y1="11" x2="14" y2="17"></line>
                        </svg>
                      </button>
                    </div>
                  </template>
                </div>
              </li>
            </template>
          </draggable>
        </div>

        <!-- New Add Item LI, integrated into the list -->
        <li class="neo-list-item new-item-input-container">
          <label class="neo-checkbox-label">
            <input type="checkbox" disabled />
            <input type="text" class="neo-new-item-input"
              :placeholder="$t('listDetailPage.items.addItemForm.placeholder')" ref="itemNameInputRef"
              :data-list-id="list?.id" @keyup.enter="onAddItem" @blur="handleNewItemBlur" v-model="newItem.name"
              @click.stop />
            <VSelect v-model="newItem.category_id" :options="categoryOptions" placeholder="Category" class="w-40"
              size="sm" />
          </label>
        </li>

        <!-- Expenses Section -->
        <section v-if="list && !itemsAreLoading" class="neo-expenses-section">
          <VCard v-if="listDetailStore.isLoading && expenses.length === 0" class="py-10 text-center">
            <VSpinner :label="$t('listDetailPage.expensesSection.loading')" size="lg" />
          </VCard>
          <VAlert v-else-if="listDetailStore.error && expenses.length === 0" type="error" class="mt-4">
            <p>{{ listDetailStore.error }}</p>
            <template #actions>
              <VButton @click="listDetailStore.fetchListWithExpenses(String(list?.id))">
                {{ $t('listDetailPage.expensesSection.retryButton') }}
              </VButton>
            </template>
          </VAlert>
          <VCard v-else-if="(!expenses || expenses.length === 0) && !listDetailStore.isLoading" variant="empty-state"
            empty-icon="receipt" :empty-title="$t('listDetailPage.expensesSection.emptyStateTitle')"
            :empty-message="$t('listDetailPage.expensesSection.emptyStateMessage')" class="mt-4">
          </VCard>
          <div v-else class="neo-expense-list">
            <div v-for="expense in expenses" :key="expense.id" class="neo-expense-item-wrapper">
              <div class="neo-expense-item" @click="toggleExpense(expense.id)"
                :class="{ 'is-expanded': isExpenseExpanded(expense.id) }">
                <div class="expense-main-content">
                  <div class="expense-icon-container">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
                      stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                      <line x1="12" x2="12" y1="2" y2="22"></line>
                      <path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path>
                    </svg>
                  </div>
                  <div class="expense-text-content">
                    <div class="neo-expense-header">
                      {{ expense.description }}
                    </div>
                    <div class="neo-expense-details">
                      {{ formatCurrency(expense.total_amount) }} &mdash;
                      {{ $t('listDetailPage.expensesSection.paidBy') }} <strong>{{ expense.paid_by_user?.name ||
                        expense.paid_by_user?.email }}</strong>
                    </div>
                  </div>
                </div>
                <div class="expense-side-content">
                  <span class="neo-expense-status" :class="getStatusClass(expense.overall_settlement_status)">
                    {{ getOverallExpenseStatusText(expense.overall_settlement_status) }}
                  </span>
                  <div class="expense-toggle-icon">
                    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
                      stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
                      class="feather feather-chevron-down">
                      <polyline points="6 9 12 15 18 9"></polyline>
                    </svg>
                  </div>
                </div>
              </div>

              <!-- Collapsible content -->
              <div v-if="isExpenseExpanded(expense.id)" class="neo-splits-container">
                <div class="neo-splits-list">
                  <div v-for="split in expense.splits" :key="split.id" class="neo-split-item">
                    <div class="split-col split-user">
                      <strong>{{ split.user?.name || split.user?.email || `User ID: ${split.user_id}` }}</strong>
                    </div>
                    <div class="split-col split-owes">
                      {{ $t('listDetailPage.expensesSection.owes') }} <strong>{{
                        formatCurrency(split.owed_amount) }}</strong>
                    </div>
                    <div class="split-col split-status">
                      <span class="neo-expense-status" :class="getStatusClass(split.status)">
                        {{ getSplitStatusText(split.status) }}
                      </span>
                    </div>
                    <div class="split-col split-paid-info">
                      <div v-if="split.paid_at" class="paid-details">
                        {{ $t('listDetailPage.expensesSection.paidAmount') }} {{ getPaidAmountForSplitDisplay(split) }}
                        <span v-if="split.paid_at"> {{ $t('listDetailPage.expensesSection.onDate') }} {{ new
                          Date(split.paid_at).toLocaleDateString() }}</span>
                      </div>
                    </div>
                    <div class="split-col split-action">
                      <button
                        v-if="split.user_id === authStore.user?.id && split.status !== ExpenseSplitStatusEnum.PAID"
                        class="btn btn-sm btn-primary" @click="openSettleShareModal(expense, split)"
                        :disabled="isSettlementLoading">
                        {{ $t('listDetailPage.expensesSection.settleShareButton') }}
                      </button>
                    </div>
                    <ul v-if="split.settlement_activities && split.settlement_activities.length > 0"
                      class="neo-settlement-activities">
                      <li v-for="activity in split.settlement_activities" :key="activity.id">
                        {{ $t('listDetailPage.expensesSection.activityLabel') }} {{
                          formatCurrency(activity.amount_paid) }}
                        {{
                          $t('listDetailPage.expensesSection.byUser') }} {{ activity.payer?.name || `User
                        ${activity.paid_by_user_id}` }} {{ $t('listDetailPage.expensesSection.onDate') }} {{ new
                          Date(activity.paid_at).toLocaleDateString() }}
                      </li>
                    </ul>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </section>
      </div>

      <!-- Create Expense Form -->
      <CreateExpenseForm v-if="showCreateExpenseForm" :list-id="list?.id" :group-id="list?.group_id ?? undefined"
        @close="showCreateExpenseForm = false" @created="handleExpenseCreated" />

      <!-- OCR Dialog -->
      <VModal v-model="showOcrDialogState" :title="$t('listDetailPage.modals.ocr.title')"
        @update:modelValue="!$event && closeOcrDialog()">
        <template #default>
          <div v-if="ocrLoading" class="text-center">
            <VSpinner :label="$t('listDetailPage.loading.ocrProcessing')" />
          </div>
          <VList v-else-if="ocrItems.length > 0">
            <VListItem v-for="(ocrItem, index) in ocrItems" :key="index">
              <div class="flex items-center gap-2">
                <VInput type="text" v-model="ocrItem.name" class="flex-grow" required />
                <VButton variant="danger" size="sm" :icon-only="true" iconLeft="trash"
                  @click="ocrItems.splice(index, 1)" />
              </div>
            </VListItem>
          </VList>
          <VFormField v-else :label="$t('listDetailPage.modals.ocr.uploadLabel')"
            :error-message="ocrError || undefined">
            <VInput type="file" id="ocrFile" accept="image/*" @change="handleOcrFileUpload" ref="ocrFileInputRef"
              :model-value="''" />
          </VFormField>
        </template>
        <template #footer>
          <VButton variant="neutral" @click="closeOcrDialog">{{ $t('listDetailPage.buttons.cancel') }}</VButton>
          <VButton v-if="ocrItems.length > 0" type="button" variant="primary" @click="addOcrItems"
            :disabled="addingOcrItems">
            <VSpinner v-if="addingOcrItems" size="sm" :label="$t('listDetailPage.loading.addingOcrItems')" /> {{
              $t('listDetailPage.buttons.addItems') }}
          </VButton>
        </template>
      </VModal>

      <!-- Cost Summary Dialog -->
      <VModal v-model="showCostSummaryDialog" :title="$t('listDetailPage.modals.costSummary.title')"
        @update:modelValue="showCostSummaryDialog = false" size="lg">
        <template #default>
          <div v-if="costSummaryLoading" class="text-center">
            <VSpinner :label="$t('listDetailPage.loading.costSummary')" />
          </div>
          <VAlert v-else-if="costSummaryError" type="error" :message="costSummaryError" />
          <div v-else-if="listCostSummary">
            <div class="mb-3 cost-overview">
              <p><strong>{{ $t('listDetailPage.modals.costSummary.totalCostLabel') }}</strong> {{
                formatCurrency(listCostSummary.total_list_cost) }}</p>
              <p><strong>{{ $t('listDetailPage.modals.costSummary.equalShareLabel') }}</strong> {{
                formatCurrency(listCostSummary.equal_share_per_user) }}</p>
              <p><strong>{{ $t('listDetailPage.modals.costSummary.participantsLabel') }}</strong> {{
                listCostSummary.num_participating_users }}</p>
            </div>
            <h4>{{ $t('listDetailPage.modals.costSummary.userBalancesHeader') }}</h4>
            <div class="table-container mt-2">
              <table class="table">
                <thead>
                  <tr>
                    <th>{{ $t('listDetailPage.modals.costSummary.tableHeaders.user') }}</th>
                    <th class="text-right">{{ $t('listDetailPage.modals.costSummary.tableHeaders.itemsAddedValue') }}
                    </th>
                    <th class="text-right">{{ $t('listDetailPage.modals.costSummary.tableHeaders.amountDue') }}</th>
                    <th class="text-right">{{ $t('listDetailPage.modals.costSummary.tableHeaders.balance') }}</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="userShare in listCostSummary.user_balances" :key="userShare.user_id">
                    <td>{{ userShare.user_identifier }}</td>
                    <td class="text-right">{{ formatCurrency(userShare.items_added_value) }}</td>
                    <td class="text-right">{{ formatCurrency(userShare.amount_due) }}</td>
                    <td class="text-right">
                      <VBadge :text="formatCurrency(userShare.balance)"
                        :variant="parseFloat(String(userShare.balance)) >= 0 ? 'settled' : 'pending'" />
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>
          <p v-else>{{ $t('listDetailPage.modals.costSummary.emptyState') }}</p>
        </template>
        <template #footer>
          <VButton variant="primary" @click="showCostSummaryDialog = false">{{ $t('listDetailPage.buttons.close') }}
          </VButton>
        </template>
      </VModal>

      <!-- Settle Share Modal -->
      <VModal v-model="showSettleModal" :title="$t('listDetailPage.modals.settleShare.title')"
        @update:modelValue="!$event && closeSettleShareModal()" size="md">
        <template #default>
          <div v-if="isSettlementLoading" class="text-center">
            <VSpinner :label="$t('listDetailPage.loading.settlement')" />
          </div>
          <VAlert v-else-if="settleAmountError" type="error" :message="settleAmountError" />
          <div v-else>
            <p>{{ $t('listDetailPage.modals.settleShare.settleAmountFor', {
              userName: selectedSplitForSettlement?.user?.name
                || selectedSplitForSettlement?.user?.email || `User ID: ${selectedSplitForSettlement?.user_id}`
            }) }}</p>
            <VFormField :label="$t('listDetailPage.modals.settleShare.amountLabel')"
              :error-message="settleAmountError || undefined">
              <VInput type="number" v-model="settleAmount" id="settleAmount" required />
            </VFormField>
          </div>
        </template>
        <template #footer>
          <VButton variant="neutral" @click="closeSettleShareModal">{{
            $t('listDetailPage.modals.settleShare.cancelButton')
            }}</VButton>
          <VButton variant="primary" @click="handleConfirmSettle">{{
            $t('listDetailPage.modals.settleShare.confirmButton')
            }}</VButton>
        </template>
      </VModal>

      <VAlert v-if="!list && !pageInitialLoad" type="info" :message="$t('listDetailPage.errors.genericLoadFailure')" />
    </template>
  </main>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, nextTick, computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { apiClient, API_ENDPOINTS } from '@/services/api';
import { useEventListener, useFileDialog, useNetwork } from '@vueuse/core';
import { useNotificationStore } from '@/stores/notifications';
import { useOfflineStore, type CreateListItemPayload } from '@/stores/offline';
import { useListDetailStore } from '@/stores/listDetailStore';
import type { ListWithExpenses } from '@/types/list';
import type { Expense, ExpenseSplit } from '@/types/expense';
import { ExpenseOverallStatusEnum, ExpenseSplitStatusEnum } from '@/types/expense';
import { useAuthStore } from '@/stores/auth';
import { Decimal } from 'decimal.js';
import type { SettlementActivityCreate } from '@/types/expense';
import SettleShareModal from '@/components/SettleShareModal.vue';
import CreateExpenseForm from '@/components/CreateExpenseForm.vue';
import type { Item } from '@/types/item';
import VHeading from '@/components/valerie/VHeading.vue';
import VSpinner from '@/components/valerie/VSpinner.vue';
import VAlert from '@/components/valerie/VAlert.vue';
import VButton from '@/components/valerie/VButton.vue';
import VBadge from '@/components/valerie/VBadge.vue';
import VIcon from '@/components/valerie/VIcon.vue';
import VModal from '@/components/valerie/VModal.vue';
import VFormField from '@/components/valerie/VFormField.vue';
import VInput from '@/components/valerie/VInput.vue';
import VList from '@/components/valerie/VList.vue';
import VListItem from '@/components/valerie/VListItem.vue';
import VCheckbox from '@/components/valerie/VCheckbox.vue';
import VProgressBar from '@/components/valerie/VProgressBar.vue';
import VToggleSwitch from '@/components/valerie/VToggleSwitch.vue';
import draggable from 'vuedraggable';
import { useCategoryStore } from '@/stores/categoryStore';
import { storeToRefs } from 'pinia';
import ExpenseCard from '@/components/ExpenseCard.vue';

const { t } = useI18n();

// Helper to extract user-friendly error messages from API responses
const getApiErrorMessage = (err: unknown, fallbackMessageKey: string): string => {
  if (err && typeof err === 'object') {
    // Check for FastAPI/DRF-style error response
    if ('response' in err && err.response && typeof err.response === 'object' && 'data' in err.response && err.response.data) {
      const errorData = err.response.data as any; // Type assertion for easier access
      if (typeof errorData.detail === 'string') {
        return errorData.detail;
      }
      if (typeof errorData.message === 'string') { // Common alternative
        return errorData.message;
      }
      // FastAPI validation errors often come as an array of objects
      if (Array.isArray(errorData.detail) && errorData.detail.length > 0) {
        const firstError = errorData.detail[0];
        if (typeof firstError.msg === 'string' && typeof firstError.type === 'string') {
          // Construct a message like "Field 'fieldname': error message"
          // const field = firstError.loc && firstError.loc.length > 1 ? firstError.loc[1] : 'Input';
          // return `${field}: ${firstError.msg}`;
          return firstError.msg; // Simpler: just the message
        }
      }
      if (typeof errorData === 'string') { // Sometimes data itself is the error string
        return errorData;
      }
    }
    // Standard JavaScript Error object
    if (err instanceof Error && err.message) {
      return err.message;
    }
  }
  // Fallback to a translated message
  return t(fallbackMessageKey);
};

// UI-specific properties that we add to items
interface ItemWithUI extends Item {
  updating: boolean;
  deleting: boolean;
  priceInput: string | number | null;
  swiped: boolean;
  isEditing?: boolean; // For inline editing state
  editName?: string; // Temporary name for inline editing
  editQuantity?: number | string | null; // Temporary quantity for inline editing
  editCategoryId?: number | null; // Temporary category for inline editing
  showFirework?: boolean; // For firework animation
}

interface ListStatus {
  updated_at: string;
  item_count: number;
}

interface List {
  id: number;
  name: string;
  description?: string;
  is_complete: boolean;
  items: ItemWithUI[];
  version: number;
  updated_at: string;
  group_id?: number;
}

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

interface UserCostShare {
  user_id: number;
  user_identifier: string;
  items_added_value: string | number;
  amount_due: string | number;
  balance: string | number;
}

interface ListCostSummaryData {
  list_id: number;
  list_name: string;
  total_list_cost: string | number;
  num_participating_users: number;
  equal_share_per_user: string | number;
  user_balances: UserCostShare[];
}

const route = useRoute();
const { isOnline } = useNetwork();
const notificationStore = useNotificationStore();
const offlineStore = useOfflineStore();
const list = ref<List | null>(null);
const pageInitialLoad = ref(true); // True until shell is loaded or first fetch begins
const itemsAreLoading = ref(false); // True when items are actively being fetched/processed
const error = ref<string | null>(null); // For page-level errors
const addingItem = ref(false);
const pollingInterval = ref<ReturnType<typeof setInterval> | null>(null);
const lastListUpdate = ref<string | null>(null);
const lastItemCount = ref<number | null>(null);

const supermarktMode = ref(false);

const categoryStore = useCategoryStore();
const { categories } = storeToRefs(categoryStore);

const newItem = ref<{ name: string; quantity?: number | string; category_id?: number | null }>({ name: '', category_id: null });
const itemNameInputRef = ref<InstanceType<typeof VInput> | null>(null);

const categoryOptions = computed(() => {
  return [
    { label: 'No Category', value: null },
    ...categories.value.map(c => ({ label: c.name, value: c.id })),
  ];
});

// OCR
const showOcrDialogState = ref(false);
// const ocrModalRef = ref<HTMLElement | null>(null); // Removed
const ocrLoading = ref(false);
const ocrItems = ref<{ name: string }[]>([]); // Items extracted from OCR
const addingOcrItems = ref(false);
const ocrError = ref<string | null>(null);
const ocrFileInputRef = ref<InstanceType<typeof VInput> | null>(null); // Changed to VInput ref type
const { files: ocrFiles, reset: resetOcrFileDialog } = useFileDialog({
  accept: 'image/*',
  multiple: false,
});


// Cost Summary
const showCostSummaryDialog = ref(false);
// const costSummaryModalRef = ref<HTMLElement | null>(null); // Removed
const listCostSummary = ref<ListCostSummaryData | null>(null);
const costSummaryLoading = ref(false);
const costSummaryError = ref<string | null>(null);

const itemCompletionProgress = computed(() => {
  if (!list.value?.items.length) return 0;
  const completedCount = list.value.items.filter(i => i.is_complete).length;
  return (completedCount / list.value.items.length) * 100;
});

// Settle Share
const authStore = useAuthStore();
const showSettleModal = ref(false);
// const settleModalRef = ref<HTMLElement | null>(null); // Removed
const selectedSplitForSettlement = ref<ExpenseSplit | null>(null);
const parentExpenseOfSelectedSplit = ref<Expense | null>(null);
const settleAmount = ref<string>('');
const settleAmountError = ref<string | null>(null);
const isSettlementLoading = computed(() => listDetailStore.isSettlingSplit);

// Create Expense
const showCreateExpenseForm = ref(false);

// Edit Item - Refs for modal edit removed
// const showEditDialog = ref(false);
// const editingItem = ref<Item | null>(null);

// onClickOutside for ocrModalRef, costSummaryModalRef, etc. are removed as VModal handles this.

// Define a more specific type for the offline item payload
interface OfflineCreateItemPayload {
  name: string;
  quantity?: string | number; // Align with the target type from the linter error
}

const formatCurrency = (value: string | number | undefined | null): string => {
  if (value === undefined || value === null) return '$0.00';
  // Ensure that string "0.00" or "0" are handled correctly before parseFloat
  if (typeof value === 'string' && !value.trim()) return '$0.00';
  const numValue = typeof value === 'string' ? parseFloat(value) : value;
  return isNaN(numValue) ? '$0.00' : `$${numValue.toFixed(2)}`;
};

const processListItems = (items: Item[]): ItemWithUI[] => {
  return items.map(item => ({
    ...item,
    updating: false,
    deleting: false,
    priceInput: item.price || null,
    swiped: false,
    showFirework: false // Initialize firework state
  }));
};

const fetchListDetails = async () => {
  if (pageInitialLoad.value) {
    pageInitialLoad.value = false;
  }
  itemsAreLoading.value = true;
  const routeId = String(route.params.id);
  const cachedFullData = sessionStorage.getItem(`listDetailFull_${routeId}`);

  try {
    let response;
    if (cachedFullData) {
      response = { data: JSON.parse(cachedFullData) };
      sessionStorage.removeItem(`listDetailFull_${routeId}`);
    } else {
      response = await apiClient.get(API_ENDPOINTS.LISTS.BY_ID(routeId));
    }

    const rawList = response.data as ListWithExpenses;
    const localList: List = {
      id: rawList.id,
      name: rawList.name,
      description: rawList.description ?? undefined,
      is_complete: rawList.is_complete,
      items: processListItems(rawList.items),
      version: rawList.version,
      updated_at: rawList.updated_at,
      group_id: rawList.group_id ?? undefined
    };
    list.value = localList;
    lastListUpdate.value = rawList.updated_at;
    lastItemCount.value = rawList.items.length;

    if (showCostSummaryDialog.value) {
      await fetchListCostSummary();
    }
  } catch (err: unknown) {
    const errorMessage = getApiErrorMessage(err, 'listDetailPage.errors.fetchFailed');
    if (!list.value) {
      error.value = errorMessage;
    } else {
      notificationStore.addNotification({ message: t('listDetailPage.errors.fetchItemsFailed', { errorMessage }), type: 'error' });
    }
  } finally {
    itemsAreLoading.value = false;
    if (!list.value && !error.value) {
      pageInitialLoad.value = false;
    }
  }
};

const checkForUpdates = async () => {
  if (!list.value) return;
  try {
    const response = await apiClient.get(API_ENDPOINTS.LISTS.STATUS(String(list.value.id)));
    const { updated_at: newListUpdatedAt, item_count: newItemCount } = response.data as ListStatus;

    if (
      (lastListUpdate.value && newListUpdatedAt > lastListUpdate.value) ||
      (lastItemCount.value !== null && newItemCount !== lastItemCount.value)
    ) {
      await fetchListDetails();
    }
  } catch (err) {
    console.warn('Polling for updates failed:', err);
  }
};

const startPolling = () => {
  stopPolling();
  pollingInterval.value = setInterval(() => checkForUpdates(), 15000);
};
const stopPolling = () => {
  if (pollingInterval.value) clearInterval(pollingInterval.value);
};

const isItemPendingSync = (item: Item) => {
  return offlineStore.pendingActions.some(action => {
    if (action.type === 'update_list_item' || action.type === 'delete_list_item') {
      const payload = action.payload as { listId: string; itemId: string };
      return payload.itemId === String(item.id);
    }
    return false;
  });
};

const handleNewItemBlur = (event: Event) => {
  const inputElement = event.target as HTMLInputElement;
  if (inputElement.value.trim()) {
    newItem.value.name = inputElement.value.trim();
    onAddItem();
  }
};

const onAddItem = async () => {
  const itemName = newItem.value.name.trim();

  if (!list.value || !itemName) {
    notificationStore.addNotification({ message: t('listDetailPage.notifications.enterItemName'), type: 'warning' });
    if (itemNameInputRef.value?.$el) {
      (itemNameInputRef.value.$el as HTMLElement).focus();
    }
    return;
  }
  addingItem.value = true;

  const optimisticItem: ItemWithUI = {
    id: Date.now(),
    name: itemName,
    quantity: typeof newItem.value.quantity === 'string' ? Number(newItem.value.quantity) : (newItem.value.quantity || null),
    is_complete: false,
    price: null,
    version: 1,
    category_id: newItem.value.category_id,
    updated_at: new Date().toISOString(),
    created_at: new Date().toISOString(),
    list_id: list.value.id,
    updating: false,
    deleting: false,
    priceInput: null,
    swiped: false
  };

  list.value.items.push(optimisticItem);

  newItem.value.name = '';
  newItem.value.category_id = null;
  if (itemNameInputRef.value?.$el) {
    (itemNameInputRef.value.$el as HTMLElement).focus();
  }

  if (!isOnline.value) {
    const offlinePayload: OfflineCreateItemPayload = {
      name: itemName
    };

    const rawQuantity = newItem.value.quantity;
    if (rawQuantity !== undefined && String(rawQuantity).trim() !== '') {
      const numAttempt = Number(rawQuantity);
      if (!isNaN(numAttempt)) {
        offlinePayload.quantity = numAttempt;
      } else {
        offlinePayload.quantity = String(rawQuantity);
      }
    }
    if (newItem.value.category_id) {
      offlinePayload.category_id = newItem.value.category_id;
    }

    offlineStore.addAction({
      type: 'create_list_item',
      payload: {
        listId: String(list.value.id),
        itemData: offlinePayload
      }
    });

    addingItem.value = false;
    notificationStore.addNotification({ message: t('listDetailPage.notifications.itemAddedSuccess'), type: 'success' });
    return;
  }

  try {
    const response = await apiClient.post(
      API_ENDPOINTS.LISTS.ITEMS(String(list.value.id)),
      {
        name: itemName,
        quantity: newItem.value.quantity ? String(newItem.value.quantity) : null,
        category_id: newItem.value.category_id,
      }
    );

    const addedItem = response.data as Item;
    const index = list.value.items.findIndex(i => i.id === optimisticItem.id);
    if (index !== -1) {
      list.value.items[index] = processListItems([addedItem])[0];
    }

    notificationStore.addNotification({ message: t('listDetailPage.notifications.itemAddedSuccess'), type: 'success' });
  } catch (err) {
    list.value.items = list.value.items.filter(i => i.id !== optimisticItem.id);
    notificationStore.addNotification({
      message: getApiErrorMessage(err, 'listDetailPage.errors.addItemFailed'),
      type: 'error'
    });
  } finally {
    addingItem.value = false;
  }
};

const updateItem = async (item: ItemWithUI, newCompleteStatus: boolean) => {
  if (!list.value) return;
  item.updating = true;
  const originalCompleteStatus = item.is_complete;
  item.is_complete = newCompleteStatus;

  const triggerFirework = () => {
    if (newCompleteStatus && !originalCompleteStatus) {
      item.showFirework = true;
      setTimeout(() => {
        if (list.value && list.value.items.find(i => i.id === item.id)) {
          item.showFirework = false;
        }
      }, 700);
    }
  };

  if (!isOnline.value) {
    offlineStore.addAction({
      type: 'update_list_item',
      payload: {
        listId: String(list.value.id),
        itemId: String(item.id),
        data: {
          completed: newCompleteStatus
        },
        version: item.version
      }
    });
    item.updating = false;
    notificationStore.addNotification({ message: t('listDetailPage.notifications.itemUpdatedSuccess'), type: 'success' });
    triggerFirework();
    return;
  }

  try {
    await apiClient.put(
      API_ENDPOINTS.LISTS.ITEM(String(list.value.id), String(item.id)),
      { completed: newCompleteStatus, version: item.version }
    );
    item.version++;
    notificationStore.addNotification({ message: t('listDetailPage.notifications.itemUpdatedSuccess'), type: 'success' });
    triggerFirework();
  } catch (err) {
    item.is_complete = originalCompleteStatus;
    notificationStore.addNotification({ message: getApiErrorMessage(err, 'listDetailPage.errors.updateItemFailed'), type: 'error' });
  } finally {
    item.updating = false;
  }
};

const updateItemPrice = async (item: ItemWithUI) => {
  if (!list.value || !item.is_complete) return;
  const newPrice = item.priceInput !== undefined && String(item.priceInput).trim() !== '' ? parseFloat(String(item.priceInput)) : null;
  if (item.price === newPrice?.toString()) return;
  item.updating = true;
  const originalPrice = item.price;
  const originalPriceInput = item.priceInput;
  item.price = newPrice?.toString() || null;

  if (!isOnline.value) {
    offlineStore.addAction({
      type: 'update_list_item',
      payload: {
        listId: String(list.value.id),
        itemId: String(item.id),
        data: {
          price: newPrice ?? null,
          completed: item.is_complete
        },
        version: item.version
      }
    });
    item.updating = false;
    notificationStore.addNotification({ message: t('listDetailPage.notifications.itemUpdatedSuccess'), type: 'success' });
    return;
  }

  try {
    await apiClient.put(
      API_ENDPOINTS.LISTS.ITEM(String(list.value.id), String(item.id)),
      { price: newPrice?.toString(), completed: item.is_complete, version: item.version }
    );
    item.version++;
    notificationStore.addNotification({ message: t('listDetailPage.notifications.itemUpdatedSuccess'), type: 'success' });
  } catch (err) {
    item.price = originalPrice;
    item.priceInput = originalPriceInput;
    notificationStore.addNotification({ message: getApiErrorMessage(err, 'listDetailPage.errors.updateItemPriceFailed'), type: 'error' });
  } finally {
    item.updating = false;
  }
};

const deleteItem = async (item: ItemWithUI) => {
  if (!list.value) return;
  item.deleting = true;
  const originalItems = [...list.value.items];

  if (!isOnline.value) {
    offlineStore.addAction({
      type: 'delete_list_item',
      payload: {
        listId: String(list.value.id),
        itemId: String(item.id)
      }
    });
    list.value.items = list.value.items.filter(i => i.id !== item.id);
    item.deleting = false;
    notificationStore.addNotification({ message: t('listDetailPage.notifications.itemDeleteSuccess'), type: 'success' });
    return;
  }

  try {
    await apiClient.delete(API_ENDPOINTS.LISTS.ITEM(String(list.value.id), String(item.id)));
    list.value.items = list.value.items.filter(i => i.id !== item.id);
    notificationStore.addNotification({ message: t('listDetailPage.notifications.itemDeleteSuccess'), type: 'success' });
  } catch (err) {
    list.value.items = originalItems;
    notificationStore.addNotification({ message: getApiErrorMessage(err, 'listDetailPage.errors.deleteItemFailed'), type: 'error' });
  } finally {
    item.deleting = false;
  }
};

const confirmUpdateItem = (item: ItemWithUI, newCompleteStatus: boolean) => {
  updateItem(item, newCompleteStatus);
};

const confirmDeleteItem = (item: ItemWithUI) => {
  deleteItem(item);
};

const openOcrDialog = () => {
  ocrItems.value = [];
  ocrError.value = null;
  resetOcrFileDialog();
  showOcrDialogState.value = true;
  nextTick(() => {
    if (ocrFileInputRef.value && ocrFileInputRef.value.$el) {
      const inputElement = ocrFileInputRef.value.$el.querySelector('input[type="file"]') || ocrFileInputRef.value.$el;
      if (inputElement) (inputElement as HTMLInputElement).value = '';
    } else if (ocrFileInputRef.value) {
      (ocrFileInputRef.value as any).value = '';
    }
  });
};
const closeOcrDialog = () => {
  showOcrDialogState.value = false;
  ocrItems.value = [];
  ocrError.value = null;
};

watch(ocrFiles, async (newFiles) => {
  if (newFiles && newFiles.length > 0) {
    const file = newFiles[0];
    await handleOcrUpload(file);
  }
});

const handleOcrFileUpload = (event: Event) => {
  const target = event.target as HTMLInputElement;
  if (target.files && target.files.length > 0) {
    handleOcrUpload(target.files[0]);
  }
};

const handleOcrUpload = async (file: File) => {
  if (!file) return;
  ocrLoading.value = true;
  ocrError.value = null;
  ocrItems.value = [];
  try {
    const formData = new FormData();
    formData.append('image_file', file);
    const response = await apiClient.post(API_ENDPOINTS.OCR.PROCESS, formData, {
      headers: { 'Content-Type': 'multipart/form-data' }
    });
    ocrItems.value = response.data.extracted_items.map((nameStr: string) => ({ name: nameStr.trim() })).filter((item: { name: string }) => item.name);
    if (ocrItems.value.length === 0) {
      ocrError.value = t('listDetailPage.errors.ocrNoItems');
    }
  } catch (err) {
    ocrError.value = getApiErrorMessage(err, 'listDetailPage.errors.ocrFailed');
  } finally {
    ocrLoading.value = false;
    if (ocrFileInputRef.value && ocrFileInputRef.value.$el) {
      const inputElement = ocrFileInputRef.value.$el.querySelector('input[type="file"]') || ocrFileInputRef.value.$el;
      if (inputElement) (inputElement as HTMLInputElement).value = '';
    } else if (ocrFileInputRef.value) {
      (ocrFileInputRef.value as any).value = '';
    }
  }
};

const addOcrItems = async () => {
  if (!list.value || !ocrItems.value.length) return;
  addingOcrItems.value = true;
  let successCount = 0;
  try {
    for (const item of ocrItems.value) {
      if (!item.name.trim()) continue;
      const response = await apiClient.post(
        API_ENDPOINTS.LISTS.ITEMS(String(list.value.id)),
        { name: item.name, quantity: "1" }
      );
      const addedItem = response.data as Item;
      list.value.items.push(processListItems([addedItem])[0]);
      successCount++;
    }
    if (successCount > 0) {
      notificationStore.addNotification({ message: t('listDetailPage.notifications.itemsAddedSuccessOcr', { count: successCount }), type: 'success' });
    }
    closeOcrDialog();
  } catch (err) {
    notificationStore.addNotification({ message: getApiErrorMessage(err, 'listDetailPage.errors.addOcrItemsFailed'), type: 'error' });
  } finally {
    addingOcrItems.value = false;
  }
};

const fetchListCostSummary = async () => {
  if (!list.value || list.value.id === 0) return;
  costSummaryLoading.value = true;
  costSummaryError.value = null;
  try {
    const response = await apiClient.get(API_ENDPOINTS.COSTS.LIST_SUMMARY(list.value.id));
    listCostSummary.value = response.data;
  } catch (err) {
    costSummaryError.value = getApiErrorMessage(err, 'listDetailPage.errors.loadCostSummaryFailed');
    listCostSummary.value = null;
  } finally {
    costSummaryLoading.value = false;
  }
};
watch(showCostSummaryDialog, (newVal) => {
  if (newVal && (!listCostSummary.value || listCostSummary.value.list_id !== list.value?.id)) {
    fetchListCostSummary();
  }
});

// --- Expense and Settlement Status Logic ---
const listDetailStore = useListDetailStore();
const expenses = computed(() => listDetailStore.getExpenses);
const allFetchedGroups = ref<Group[]>([]);

const getGroupName = (groupId: number): string => {
  const group = allFetchedGroups.value.find((g: Group) => g.id === groupId);
  return group?.name || `Group ${groupId}`;
};

const getPaidAmountForSplitDisplay = (split: ExpenseSplit): string => {
  const amount = listDetailStore.getPaidAmountForSplit(split.id);
  return formatCurrency(amount);
};

const getSplitStatusText = (status: ExpenseSplitStatusEnum): string => {
  switch (status) {
    case ExpenseSplitStatusEnum.PAID: return t('listDetailPage.status.paid');
    case ExpenseSplitStatusEnum.PARTIALLY_PAID: return t('listDetailPage.status.partiallyPaid');
    case ExpenseSplitStatusEnum.UNPAID: return t('listDetailPage.status.unpaid');
    default: return t('listDetailPage.status.unknown');
  }
};

const getOverallExpenseStatusText = (status: ExpenseOverallStatusEnum): string => {
  switch (status) {
    case ExpenseOverallStatusEnum.PAID: return t('listDetailPage.status.settled');
    case ExpenseOverallStatusEnum.PARTIALLY_PAID: return t('listDetailPage.status.partiallySettled');
    case ExpenseOverallStatusEnum.UNPAID: return t('listDetailPage.status.unsettled');
    default: return t('listDetailPage.status.unknown');
  }
};

const getStatusClass = (status: ExpenseSplitStatusEnum | ExpenseOverallStatusEnum): string => {
  if (status === ExpenseSplitStatusEnum.PAID || status === ExpenseOverallStatusEnum.PAID) return 'status-paid';
  if (status === ExpenseSplitStatusEnum.PARTIALLY_PAID || status === ExpenseOverallStatusEnum.PARTIALLY_PAID) return 'status-partially_paid';
  if (status === ExpenseSplitStatusEnum.UNPAID || status === ExpenseOverallStatusEnum.UNPAID) return 'status-unpaid';
  return '';
};

useEventListener(window, 'keydown', (event: KeyboardEvent) => {
  if (event.key === 'n' && !event.ctrlKey && !event.metaKey && !event.altKey) {
    const activeElement = document.activeElement;
    if (activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA')) {
      return;
    }
    if (showOcrDialogState.value || showCostSummaryDialog.value || showSettleModal.value || showCreateExpenseForm.value) {
      return;
    }
    event.preventDefault();
    if (itemNameInputRef.value?.$el) {
      (itemNameInputRef.value.$el as HTMLElement).focus();
    }
  }
});

onMounted(() => {
  pageInitialLoad.value = true;
  itemsAreLoading.value = false;
  error.value = null;

  if (!route.params.id) {
    error.value = t('listDetailPage.errors.fetchFailed');
    pageInitialLoad.value = false;
    listDetailStore.setError(t('listDetailPage.errors.fetchFailed'));
    return;
  }

  const listShellJSON = sessionStorage.getItem('listDetailShell');
  const routeId = String(route.params.id);

  if (listShellJSON) {
    const shellData = JSON.parse(listShellJSON);
    if (shellData.id === parseInt(routeId, 10)) {
      list.value = {
        id: shellData.id,
        name: shellData.name,
        description: shellData.description,
        is_complete: false,
        items: [],
        version: 0,
        updated_at: new Date().toISOString(),
        group_id: shellData.group_id,
      };
      pageInitialLoad.value = false;
    } else {
      sessionStorage.removeItem('listDetailShell');
    }
  }

  // Fetch categories relevant to the list (either personal or group)
  categoryStore.fetchCategories(list.value?.group_id);

  fetchListDetails().then(() => {
    startPolling();
  });
  const routeParamsId = route.params.id;
  listDetailStore.fetchListWithExpenses(String(routeParamsId));
});

onUnmounted(() => {
  stopPolling();
});

const startItemEdit = (item: ItemWithUI) => {
  list.value?.items.forEach(i => { if (i.id !== item.id) i.isEditing = false; });
  item.isEditing = true;
  item.editName = item.name;
  item.editQuantity = item.quantity ?? '';
  item.editCategoryId = item.category_id;
};

const cancelItemEdit = (item: ItemWithUI) => {
  item.isEditing = false;
};

const saveItemEdit = async (item: ItemWithUI) => {
  if (!list.value || !item.editName || String(item.editName).trim() === '') {
    notificationStore.addNotification({
      message: t('listDetailPage.notifications.enterItemName'),
      type: 'warning'
    });
    return;
  }

  const payload = {
    name: String(item.editName).trim(),
    quantity: item.editQuantity ? String(item.editQuantity) : null,
    version: item.version,
    category_id: item.editCategoryId,
  };

  item.updating = true;

  try {
    const response = await apiClient.put(
      API_ENDPOINTS.LISTS.ITEM(String(list.value.id), String(item.id)),
      payload
    );

    const updatedItemFromApi = response.data as Item;
    item.name = updatedItemFromApi.name;
    item.quantity = updatedItemFromApi.quantity;
    item.version = updatedItemFromApi.version;
    item.is_complete = updatedItemFromApi.is_complete;
    item.price = updatedItemFromApi.price;
    item.updated_at = updatedItemFromApi.updated_at;
    item.category_id = updatedItemFromApi.category_id;

    item.isEditing = false;
    notificationStore.addNotification({
      message: t('listDetailPage.notifications.itemUpdatedSuccess'),
      type: 'success'
    });

  } catch (err) {
    notificationStore.addNotification({
      message: getApiErrorMessage(err, 'listDetailPage.errors.updateItemFailed'),
      type: 'error'
    });
  } finally {
    item.updating = false;
  }
};

const openSettleShareModal = (expense: Expense, split: ExpenseSplit) => {
  if (split.user_id !== authStore.user?.id) {
    notificationStore.addNotification({ message: t('listDetailPage.notifications.cannotSettleOthersShares'), type: 'warning' });
    return;
  }
  selectedSplitForSettlement.value = split;
  parentExpenseOfSelectedSplit.value = expense;
  const alreadyPaid = new Decimal(listDetailStore.getPaidAmountForSplit(split.id));
  const owed = new Decimal(split.owed_amount);
  const remaining = owed.minus(alreadyPaid);
  settleAmount.value = remaining.toFixed(2);
  settleAmountError.value = null;
  showSettleModal.value = true;
};

const closeSettleShareModal = () => {
  showSettleModal.value = false;
  selectedSplitForSettlement.value = null;
  parentExpenseOfSelectedSplit.value = null;
  settleAmount.value = '';
  settleAmountError.value = null;
};

const validateSettleAmount = (): boolean => {
  settleAmountError.value = null;
  if (!settleAmount.value.trim()) {
    settleAmountError.value = t('listDetailPage.modals.settleShare.errors.enterAmount');
    return false;
  }
  const amount = new Decimal(settleAmount.value);
  if (amount.isNaN() || amount.isNegative() || amount.isZero()) {
    settleAmountError.value = t('listDetailPage.modals.settleShare.errors.positiveAmount');
    return false;
  }
  if (selectedSplitForSettlement.value) {
    const alreadyPaid = new Decimal(listDetailStore.getPaidAmountForSplit(selectedSplitForSettlement.value.id));
    const owed = new Decimal(selectedSplitForSettlement.value.owed_amount);
    const remaining = owed.minus(alreadyPaid);
    if (amount.greaterThan(remaining.plus(new Decimal('0.001')))) {
      settleAmountError.value = t('listDetailPage.modals.settleShare.errors.exceedsRemaining', { amount: formatCurrency(remaining.toFixed(2)) });
      return false;
    }
  } else {
    settleAmountError.value = t('listDetailPage.modals.settleShare.errors.noSplitSelected');
    return false;
  }
  return true;
};

const currentListIdForRefetch = computed(() => listDetailStore.currentList?.id || null);

const handleConfirmSettle = async () => {
  if (!selectedSplitForSettlement.value || !authStore.user?.id || !currentListIdForRefetch.value) {
    notificationStore.addNotification({ message: t('listDetailPage.notifications.settlementDataMissing'), type: 'error' });
    return;
  }

  const activityData: SettlementActivityCreate = {
    expense_split_id: selectedSplitForSettlement.value.id,
    paid_by_user_id: Number(authStore.user.id),
    amount_paid: new Decimal(settleAmount.value).toString(),
    paid_at: new Date().toISOString(),
  };

  const success = await listDetailStore.settleExpenseSplit({
    list_id_for_refetch: String(currentListIdForRefetch.value),
    expense_split_id: selectedSplitForSettlement.value.id,
    activity_data: activityData,
  });

  if (success) {
    notificationStore.addNotification({ message: t('listDetailPage.notifications.settleShareSuccess'), type: 'success' });
    closeSettleShareModal();
  } else {
    notificationStore.addNotification({ message: listDetailStore.error || t('listDetailPage.notifications.settleShareFailed'), type: 'error' });
  }
};

const handleExpenseCreated = (expense: any) => {
  if (list.value?.id) {
    listDetailStore.fetchListWithExpenses(String(list.value.id));
  }
};

const handleCheckboxChange = (item: ItemWithUI, event: Event) => {
  const target = event.target as HTMLInputElement;
  if (target) {
    updateItem(item, target.checked);
  }
};

const handleDragEnd = async (evt: any) => {
  if (!list.value || evt.oldIndex === evt.newIndex) return;

  const originalList = [...list.value.items];
  const item = list.value.items[evt.newIndex];
  const newPosition = evt.newIndex + 1;

  try {
    await apiClient.put(
      API_ENDPOINTS.LISTS.ITEM(String(list.value.id), String(item.id)),
      { position: newPosition, version: item.version }
    );
    const updatedItemInList = list.value.items.find(i => i.id === item.id);
    if (updatedItemInList) {
      updatedItemInList.version++;
    }
    notificationStore.addNotification({
      message: t('listDetailPage.notifications.itemReorderedSuccess'),
      type: 'success'
    });
  } catch (err) {
    list.value.items = originalList;
    notificationStore.addNotification({
      message: getApiErrorMessage(err, 'listDetailPage.errors.reorderItemFailed'),
      type: 'error'
    });
  }
};

const expandedExpenses = ref<Set<number>>(new Set());

const toggleExpense = (expenseId: number) => {
  const newSet = new Set(expandedExpenses.value);
  if (newSet.has(expenseId)) {
    newSet.delete(expenseId);
  } else {
    newSet.add(expenseId);
  }
  expandedExpenses.value = newSet;
};

const isExpenseExpanded = (expenseId: number) => {
  return expandedExpenses.value.has(expenseId);
};

const groupedItems = computed(() => {
  if (!list.value?.items) return [];
  const groups: Record<string, { categoryName: string; items: ItemWithUI[] }> = {};

  list.value.items.forEach(item => {
    const categoryId = item.category_id;
    const category = categories.value.find(c => c.id === categoryId);
    const categoryName = category ? category.name : t('listDetailPage.items.noCategory');

    if (!groups[categoryName]) {
      groups[categoryName] = { categoryName, items: [] };
    }
    groups[categoryName].items.push(item);
  });

  return Object.values(groups);
});

</script>

<style scoped>
.neo-expenses-section {
  padding: 0;
  margin-top: 1.2rem;
}

.neo-expense-list {
  background-color: rgb(255, 248, 240);
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid #f0e5d8;
}

.neo-expense-item-wrapper {
  border-bottom: 1px solid #f0e5d8;
}

.neo-expense-item-wrapper:last-child {
  border-bottom: none;
}

.neo-expense-item {
  padding: 1rem 1.2rem;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: background-color 0.2s ease;
}

.neo-expense-item:hover {
  background-color: rgba(0, 0, 0, 0.02);
}

.neo-expense-item.is-expanded .expense-toggle-icon {
  transform: rotate(180deg);
}

.expense-main-content {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.expense-icon-container {
  color: #d99a53;
}

.expense-text-content {
  display: flex;
  flex-direction: column;
}

.expense-side-content {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.expense-toggle-icon {
  color: #888;
  transition: transform 0.3s ease;
}

.neo-expense-header {
  font-size: 1.1rem;
  font-weight: 600;
  margin-bottom: 0.1rem;
}

.neo-expense-details,
.neo-split-details {
  font-size: 0.9rem;
  color: #555;
  margin-bottom: 0.3rem;
}

.neo-expense-details strong,
.neo-split-details strong {
  color: #111;
}

.neo-expense-status {
  display: inline-block;
  padding: 0.25em 0.6em;
  font-size: 0.85em;
  font-weight: 700;
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  vertical-align: baseline;
  border-radius: 0.375rem;
  margin-left: 0.5rem;
  color: #22c55e;
}

.status-unpaid {
  background-color: #fee2e2;
  color: #dc2626;
}

.status-partially_paid {
  background-color: #ffedd5;
  color: #f97316;
}

.status-paid {
  background-color: #dcfce7;
  color: #22c55e;
}

.neo-splits-container {
  padding: 0.5rem 1.2rem 1.2rem;
  background-color: rgba(255, 255, 255, 0.5);
}

.neo-splits-list {
  margin-top: 0rem;
  padding-left: 0;
  border-left: none;
}

.neo-split-item {
  padding: 0.75rem 0;
  border-bottom: 1px dashed #f0e5d8;
  display: grid;
  grid-template-areas:
    "user owes status paid action"
    "activities activities activities activities activities";
  grid-template-columns: 1.5fr 1fr 1fr 1.5fr auto;
  gap: 0.5rem 1rem;
  align-items: center;
}

.neo-split-item:last-child {
  border-bottom: none;
}

.split-col.split-user {
  grid-area: user;
}

.split-col.split-owes {
  grid-area: owes;
}

.split-col.split-status {
  grid-area: status;
}

.split-col.split-paid-info {
  grid-area: paid;
}

.split-col.split-action {
  grid-area: action;
  justify-self: end;
}

.split-col.neo-settlement-activities {
  grid-area: activities;
  font-size: 0.8em;
  color: #555;
  padding-left: 1em;
  list-style-type: disc;
  margin-top: 0.5em;
}

.neo-settlement-activities {
  font-size: 0.8em;
  color: #555;
  padding-left: 1em;
  list-style-type: disc;
  margin-top: 0.5em;
}

.neo-settlement-activities li {
  margin-top: 0.2em;
}

.neo-container {
  padding: 1rem;
  max-width: 1200px;
  margin: 0 auto;
}

.page-padding {
  padding-inline: 0;
  padding-block-start: 1rem;
  padding-block-end: 5rem;
  max-width: 1200px;
  margin: 0 auto;
}

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

.neo-loading-state,
.neo-error-state,
.neo-empty-state {
  text-align: center;
  padding: 3rem 1rem;
  margin: 2rem 0;
  border: 3px solid #111;
  border-radius: 18px;
  background: #fff;
  box-shadow: 6px 6px 0 #111;
}

.neo-error-state {
  border-color: #e74c3c;
}

.neo-list-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.neo-title {
  font-size: 2.5rem;
  font-weight: 900;
  margin: 0;
  line-height: 1.2;
}

.neo-header-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.neo-description-internal {
  font-size: 1.2rem;
  color: #555;
  margin-top: 0.75rem;
  margin-bottom: 1rem;
}

.neo-status {
  font-weight: 900;
  font-size: 1rem;
  padding: 0.4rem 1rem;
  border: 3px solid #111;
  border-radius: 50px;
  background: var(--light);
  box-shadow: 3px 3px 0 #111;
}

.neo-item-list-container {
  border: 3px solid #111;
  border-radius: 18px;
  background: var(--light);
  box-shadow: 6px 6px 0 #111;
  overflow: hidden;
}

.neo-list-card-header {
  padding: 1rem 1.2rem;
  border-bottom: 1px solid #eee;
}

.neo-list-header-main {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.neo-list-title-group {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.neo-item-list {
  list-style: none;
  padding: 1.2rem;
  padding-inline: 0;
  margin-bottom: 0;
  border-bottom: 1px solid #eee;
  background: var(--light);
}

.neo-list-item {
  padding: 1rem 0;
  border-bottom: 1px solid #eee;
  transition: background-color 0.2s ease;
}

.neo-list-item:last-child {
  border-bottom: none;
}

.neo-list-item:hover {
  background-color: #f8f8f8;
}

@media (max-width: 600px) {
  .neo-list-item {
    padding: 0.75rem 1rem;
  }
}

.item-pending-sync {}

.neo-icon-button {
  padding: 0.5rem;
  border-radius: 4px;
  color: #666;
  transition: all 0.2s ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  cursor: pointer;
}

.neo-icon-button:hover {
  background: #f0f0f0;
  color: #333;
}

.neo-edit-button {
  color: #3b82f6;
}

.neo-edit-button:hover {
  background: #eef7fd;
  color: #2563eb;
}

.neo-delete-button {
  color: #ef4444;
}

.neo-delete-button:hover {
  background: #fee2e2;
  color: #dc2626;
}

.neo-save-button {
  color: #22c55e;
}

.neo-save-button:hover {
  background: #dcfce7;
  color: #16a34a;
}

.neo-cancel-button {
  color: #ef4444;
}

.neo-cancel-button:hover {
  background: #fee2e2;
  color: #dc2626;
}

/* Custom Checkbox Styles */
.neo-checkbox-label {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 0.8em;
  cursor: pointer;
  position: relative;
  width: 100%;
  font-weight: 500;
  color: #414856;
  transition: color 0.3s ease;
}

.neo-checkbox-label input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  position: relative;
  height: 20px;
  width: 20px;
  outline: none;
  border: 2px solid #b8c1d1;
  margin: 0;
  cursor: pointer;
  background: transparent;
  border-radius: 6px;
  display: grid;
  align-items: center;
  justify-content: center;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.neo-checkbox-label input[type="checkbox"]:hover {
  border-color: var(--secondary);
  transform: scale(1.05);
}

.neo-checkbox-label input[type="checkbox"]::before,
.neo-checkbox-label input[type="checkbox"]::after {
  content: none;
}

.neo-checkbox-label input[type="checkbox"]::after {
  content: "";
  position: absolute;
  opacity: 0;
  left: 5px;
  top: 1px;
  width: 6px;
  height: 12px;
  border: solid var(--primary);
  border-width: 0 3px 3px 0;
  transform: rotate(45deg) scale(0);
  transition: all 0.2s cubic-bezier(0.18, 0.89, 0.32, 1.28);
  transition-property: transform, opacity;
}

.neo-checkbox-label input[type="checkbox"]:checked {
  border-color: var(--primary);
}

.neo-checkbox-label input[type="checkbox"]:checked::after {
  opacity: 1;
  transform: rotate(45deg) scale(1);
}

.checkbox-content {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
}

.checkbox-text-span {
  position: relative;
  transition: color 0.4s ease, opacity 0.4s ease;
  width: fit-content;
}

/* Animated strikethrough line */
.checkbox-text-span::before {
  content: '';
  position: absolute;
  top: 50%;
  left: -0.1em;
  right: -0.1em;
  height: 2px;
  background: var(--dark);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s cubic-bezier(0.77, 0, .18, 1);
}

/* Firework particle container */
.checkbox-text-span::after {
  content: '';
  position: absolute;
  width: 6px;
  height: 6px;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  pointer-events: none;
}

/* Selector fixed to target span correctly */
.neo-checkbox-label input[type="checkbox"]:checked~.checkbox-content .checkbox-text-span {
  color: var(--dark);
  opacity: 0.6;
}

.neo-checkbox-label input[type="checkbox"]:checked~.checkbox-content .checkbox-text-span::before {
  transform: scaleX(1);
  transform-origin: left;
  transition: transform 0.4s cubic-bezier(0.77, 0, .18, 1) 0.1s;
}

.neo-checkbox-label input[type="checkbox"]:checked~.checkbox-content .checkbox-text-span::after {
  animation: firework-refined 0.7s cubic-bezier(0.4, 0, 0.2, 1) forwards 0.2s;
}

.neo-completed-static {
  color: var(--dark);
  opacity: 0.6;
  position: relative;
}

/* Static strikethrough for items loaded as complete */
.neo-completed-static::before {
  content: '';
  position: absolute;
  top: 50%;
  left: -0.1em;
  right: -0.1em;
  height: 2px;
  background: var(--dark);
  transform: scaleX(1);
  transform-origin: left;
}

@keyframes firework-refined {
  from {
    opacity: 1;
    transform: translate(-50%, -50%) scale(0.5);
    box-shadow: 0 0 0 0 var(--accent), 0 0 0 0 var(--accent), 0 0 0 0 var(--accent), 0 0 0 0 var(--accent), 0 0 0 0 var(--accent), 0 0 0 0 var(--accent), 0 0 0 0 var(--accent), 0 0 0 0 var(--accent);
  }

  to {
    opacity: 0;
    transform: translate(-50%, -50%) scale(2);
    box-shadow: 0 -20px 0 0 var(--accent), 20px 0px 0 0 var(--accent), 0 20px 0 0 var(--accent), -20px 0px 0 0 var(--accent), 14px -14px 0 0 var(--accent), 14px 14px 0 0 var(--accent), -14px 14px 0 0 var(--accent), -14px -14px 0 0 var(--accent);
  }
}

/* Update price input styling */
.neo-price-input {
  display: inline-flex;
  align-items: center;
  margin-left: 0.5rem;
  opacity: 0.7;
  transition: opacity 0.2s ease;
}

.neo-list-item:hover .neo-price-input {
  opacity: 1;
}

.neo-price-input input {
  border: 1px dashed #ccc;
  border-radius: 4px;
  padding: 0.2rem 0.4rem;
  font-size: 0.9rem;
  color: #666;
  background: transparent;
  transition: all 0.2s ease;
  width: 70px;
}

.neo-price-input input:focus {
  border-color: var(--secondary);
  outline: none;
  background: var(--light);
}

/* New item input styling */
.new-item-input-container {
  list-style: none !important;
  padding-inline: 3rem;
  padding-bottom: 1.2rem;
}

.new-item-input-container .neo-checkbox-label {

  width: 100%;
}

.neo-new-item-input {
  all: unset;
  height: 100%;
  width: 100%;
  font-size: 1.05rem;
  font-weight: 500;
  color: #444;
  padding: 0.2rem 0;
  border-bottom: 1px dashed #ccc;
  transition: border-color 0.2s ease;
}

.neo-new-item-input:focus {
  border-bottom-color: var(--secondary);
}

.neo-new-item-input::placeholder {
  color: #999;
  font-weight: 400;
}

.neo-new-item-input:disabled {
  opacity: 0.7;
  cursor: not-allowed;
  background-color: transparent;
}

/* Add item appear animation */
@keyframes item-appear {
  0% {
    opacity: 0;
    transform: translateY(-15px);
  }

  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

.item-appear {
  animation: item-appear 0.35s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.neo-item-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  gap: 0.5rem;
}

.neo-item-actions {
  display: flex;
  gap: 0.25rem;
  opacity: 0;
  transition: opacity 0.2s ease;
  margin-left: auto;
}

.neo-list-item:hover .neo-item-actions {
  opacity: 1;
}

.inline-edit-form {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}

.inline-edit-form .VInput_root {
  margin-bottom: 0;
}

@media (max-width: 600px) {
  .neo-price-input input {
    width: 60px;
  }
}

.drag-handle {
  cursor: grab;
  padding: 0.5rem;
  color: #666;
  opacity: 0;
  transition: opacity 0.2s ease;
  display: flex;
  align-items: center;
  justify-content: center;
}

.neo-list-item:hover .drag-handle {
  opacity: 0.5;
}

.drag-handle:hover {
  opacity: 1 !important;
  color: #333;
}

.drag-handle:active {
  cursor: grabbing;
}

/* Update neo-item-content to accommodate drag handle */
.neo-item-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  gap: 0.5rem;
}

/* Add styles for dragging state */
.sortable-ghost {
  opacity: 0.5;
  background: #f0f0f0;
}

.sortable-drag {
  background: white;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.category-group {
  margin-bottom: 1.5rem;
}

.category-header {
  font-size: 1.5rem;
  font-weight: 700;
  margin-bottom: 0.75rem;
}

.category-group.highlight .neo-list-item:not(.is-complete) {
  background-color: #e6f7ff;
}
</style>
