<template>
  <q-page padding>
    <div v-if="loading" class="text-center">
      <q-spinner-dots color="primary" size="2em" />
      <p>Loading list details...</p>
    </div>

    <q-banner v-else-if="error" inline-actions class="text-white bg-red q-mb-md">
      <template v-slot:avatar>
        <q-icon name="warning" />
      </template>
      {{ error }}
      <template v-slot:action>
        <q-btn flat color="white" label="Retry" @click="fetchListDetails" />
      </template>
    </q-banner>

    <template v-else>
      <div class="row items-center q-mb-md">
        <h1 class="text-h4 q-mb-none">{{ list.name }}</h1>
        <q-space />
        <q-btn
          color="secondary"
          icon="camera_alt"
          label="Add via OCR"
          class="q-mr-sm"
          @click="showOcrDialog = true"
        />
        <q-badge
          :color="list.is_complete ? 'green' : 'orange'"
          :label="list.is_complete ? 'Complete' : 'Active'"
        />
      </div>

      <!-- OCR Dialog -->
      <q-dialog v-model="showOcrDialog">
        <q-card style="min-width: 350px">
          <q-card-section>
            <div class="text-h6">Add Items via OCR</div>
          </q-card-section>

          <q-card-section v-if="!ocrItems.length">
            <q-file
              v-model="ocrFile"
              label="Upload Image"
              accept="image/*"
              outlined
              @update:model-value="handleOcrUpload"
            >
              <template v-slot:prepend>
                <q-icon name="attach_file" />
              </template>
            </q-file>
            <q-inner-loading :showing="ocrLoading">
              <q-spinner-dots size="50px" color="primary" />
            </q-inner-loading>
          </q-card-section>

          <q-card-section v-else>
            <div class="text-subtitle2 q-mb-sm">Review Extracted Items</div>
            <q-list bordered separator>
              <q-item v-for="(item, index) in ocrItems" :key="index">
                <q-item-section>
                  <q-input
                    v-model="item.name"
                    outlined
                    dense
                    :rules="[(val) => !!val || 'Name is required']"
                  />
                </q-item-section>
                <q-item-section side>
                  <q-btn
                    flat
                    round
                    dense
                    icon="delete"
                    color="negative"
                    @click="ocrItems.splice(index, 1)"
                  />
                </q-item-section>
              </q-item>
            </q-list>
          </q-card-section>

          <q-card-actions align="right">
            <q-btn flat label="Cancel" color="primary" v-close-popup />
            <q-btn
              v-if="ocrItems.length"
              flat
              label="Add Items"
              color="primary"
              @click="addOcrItems"
              :loading="addingOcrItems"
            />
          </q-card-actions>
        </q-card>
      </q-dialog>

      <!-- Add Item Form -->
      <q-form @submit="onAddItem" class="q-mb-lg">
        <div class="row q-col-gutter-md">
          <div class="col-12 col-md-6">
            <q-input
              v-model="newItem.name"
              label="Item Name"
              :rules="[(val) => !!val || 'Name is required']"
              outlined
              ref="itemNameInput"
              @keydown.enter.prevent="onAddItem"
            />
          </div>
          <div class="col-12 col-md-4">
            <q-input
              v-model.number="newItem.quantity"
              type="number"
              label="Quantity (optional)"
              outlined
              min="1"
              @keydown.enter.prevent="onAddItem"
            />
          </div>
          <div class="col-12 col-md-2">
            <q-btn
              type="submit"
              color="primary"
              label="Add"
              class="full-width"
              :loading="addingItem"
            />
          </div>
        </div>
      </q-form>

      <!-- Items List -->
      <div v-if="list.items.length === 0" class="text-center q-pa-md">
        <p>No items in this list yet. Add some items above!</p>
      </div>

      <q-list v-else bordered separator>
        <q-item
          v-for="item in list.items"
          :key="item.id"
          :class="{ 'text-strike': item.is_complete }"
        >
          <q-item-section avatar>
            <q-checkbox
              v-model="item.is_complete"
              @update:model-value="confirmUpdateItem(item)"
              :loading="item.updating"
              :disable="item.updating"
            />
          </q-item-section>
          <q-item-section>
            <q-item-label>{{ item.name }}</q-item-label>
            <q-item-label caption v-if="item.quantity">
              Quantity: {{ item.quantity }}
            </q-item-label>
            <!-- Add Price Input Field when item is complete -->
            <q-input
              v-if="item.is_complete"
              v-model.number="item.price"
              type="number"
              label="Price"
              dense
              outlined
              step="0.01"
              prefix="$"
              class="q-mt-sm"
              style="max-width: 150px"
              @keydown.enter.prevent="($event.target as HTMLInputElement)?.blur()"
            />
          </q-item-section>
          <q-item-section side>
            <q-btn
              flat
              round
              dense
              icon="delete"
              color="negative"
              @click="confirmDeleteItem(item)"
              :loading="item.deleting"
              :disable="item.deleting"
            />
          </q-item-section>
        </q-item>
      </q-list>
    </template>

    <!-- Confirmation Dialog -->
    <q-dialog v-model="showConfirmDialog" persistent>
      <q-card>
        <q-card-section class="row items-center">
          <q-avatar icon="warning" color="warning" text-color="white" />
          <span class="q-ml-sm">{{ confirmDialogMessage }}</span>
        </q-card-section>

        <q-card-actions align="right">
          <q-btn flat label="Cancel" color="primary" v-close-popup />
          <q-btn flat label="Confirm" color="primary" @click="handleConfirmedAction" />
        </q-card-actions>
      </q-card>
    </q-dialog>
  </q-page>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { useRoute } from 'vue-router';
import { apiClient, API_ENDPOINTS } from 'src/config/api';
import { useQuasar, QFile } from 'quasar';

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

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

const route = useRoute();
const $q = useQuasar();

const list = ref<List>({
  id: 0,
  name: '',
  items: [],
  is_complete: false,
  version: 0,
  updated_at: '',
});
const loading = ref(true);
const error = ref<string | null>(null);
const addingItem = ref(false);
const pollingInterval = ref<NodeJS.Timeout | null>(null);
const lastListUpdate = ref<string | null>(null);
const lastItemUpdate = ref<string | null>(null);

const newItem = ref<{ name: string; quantity?: string }>({ name: '' });

// OCR related state
const showOcrDialog = ref(false);
const ocrFile = ref<File | null>(null);
const ocrLoading = ref(false);
const ocrItems = ref<{ name: string }[]>([]);
const addingOcrItems = ref(false);
const ocrError = ref<string | null>(null);

// Add new refs for confirmation dialog
const showConfirmDialog = ref(false);
const confirmDialogMessage = ref('');
const pendingAction = ref<(() => Promise<void>) | null>(null);

// Add ref for item name input
const itemNameInput = ref<{ focus: () => void } | null>(null);

const fetchListDetails = async () => {
  loading.value = true;
  error.value = null;
  console.log('Fetching list details for ID:', route.params.id);
  try {
    const response = await apiClient.get(
      API_ENDPOINTS.LISTS.BY_ID(String(route.params.id))
    );
    console.log('List details response:', response.data);
    list.value = response.data as List;
    lastListUpdate.value = response.data.updated_at;
    // Find the latest item update time
    lastItemUpdate.value = response.data.items.reduce((latest: string, item: Item) => {
      return item.updated_at > latest ? item.updated_at : latest;
    }, '');
  } catch (err: unknown) {
    console.error('Failed to fetch list details:', err);
    error.value =
      (err as Error).message ||
      'Failed to load list details. Please try again.';
    $q.notify({
      type: 'negative',
      message: error.value,
    });
  } finally {
    loading.value = false;
  }
};

const checkForUpdates = async () => {
  try {
    const response = await apiClient.get(
      API_ENDPOINTS.LISTS.BY_ID(String(route.params.id))
    );
    const { updated_at: list_updated_at } = response.data as List;
    const latest_item_updated_at = response.data.items.reduce((latest: string, item: Item) => {
      return item.updated_at > latest ? item.updated_at : latest;
    }, '');

    // If either the list or any item has been updated, refresh the data
    if (
      (lastListUpdate.value && list_updated_at > lastListUpdate.value) ||
      (lastItemUpdate.value && latest_item_updated_at > lastItemUpdate.value)
    ) {
      await fetchListDetails();
    }
  } catch (err: unknown) {
    console.error('Failed to check for updates:', err);
    // Don't show error to user for polling failures
  }
};

const startPolling = () => {
  // Poll every 15 seconds
  pollingInterval.value = setInterval(() => void checkForUpdates(), 15000);
};

const stopPolling = () => {
  if (pollingInterval.value) {
    clearInterval(pollingInterval.value);
    pollingInterval.value = null;
  }
};

const onAddItem = async () => {
  if (!newItem.value.name) {
    $q.notify({
      type: 'warning',
      message: 'Please enter an item name',
    });
    return;
  }

  addingItem.value = true;
  try {
    const response = await apiClient.post(
      API_ENDPOINTS.LISTS.ITEMS(String(list.value.id)),
      {
        name: newItem.value.name,
        quantity: newItem.value.quantity?.toString()
      }
    );
    list.value.items.push(response.data as Item);
    newItem.value = { name: '' };
    // Focus the input for the next item
    itemNameInput.value?.focus();
  } catch (err: unknown) {
    $q.notify({
      type: 'negative',
      message: (err as Error).message || 'Failed to add item',
    });
  } finally {
    addingItem.value = false;
  }
};

const updateItem = async (item: Item) => {
  item.updating = true;
  try {
    // Use the new endpoint for updating a specific item
    const response = await apiClient.put(
      API_ENDPOINTS.ITEMS.BY_ID(String(item.id)), 
      {
        // Send only relevant fields for this update action
        is_complete: item.is_complete,
        // Ensure price is a number or null. If item.price is undefined, treat as null.
        price: (item.price === undefined || item.price === null) ? null : Number(item.price),
        version: item.version,
      }
    );
    Object.assign(item, response.data as Item);
    // Ensure the price is a number locally after update, or null
    if (response.data.price !== null && response.data.price !== undefined) {
      item.price = Number(response.data.price);
    } else {
      item.price = null;
    }
  } catch (err: unknown) {
    if ((err as { response?: { status?: number } }).response?.status === 409) {
      $q.notify({
        type: 'warning',
        message: 'This item was modified elsewhere. Please refresh the page.',
      });
      // Revert the checkbox state
      item.is_complete = !item.is_complete;
    } else {
      $q.notify({
        type: 'negative',
        message: (err as Error).message || 'Failed to update item',
      });
      // Revert the checkbox state
      item.is_complete = !item.is_complete;
    }
  } finally {
    item.updating = false;
  }
};

const handleOcrUpload = async (file: File | null) => {
  if (!file) return;

  ocrLoading.value = true;
  ocrError.value = null;
  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'
        }
      }
    );
    // Transform the array of strings into an array of objects { name: string }
    ocrItems.value = response.data.extracted_items.map((nameStr: string) => ({ name: nameStr }));
    showOcrDialog.value = true;
  } catch (err: unknown) {
    ocrError.value = (err as Error).message || 'Failed to process image';
    $q.notify({
      type: 'negative',
      message: ocrError.value,
    });
  } finally {
    ocrLoading.value = false;
  }
};

const addOcrItems = async () => {
  if (!ocrItems.value.length) return;

  addingOcrItems.value = true;
  try {
    for (const item of ocrItems.value) {
      if (!item.name) continue;

      const response = await apiClient.post(
        API_ENDPOINTS.LISTS.ITEMS(String(list.value.id)),
        { name: item.name, quantity: "1" }
      );
      list.value.items.push(response.data as Item);
    }

    $q.notify({
      type: 'positive',
      message: 'Items added successfully',
    });

    showOcrDialog.value = false;
    ocrItems.value = [];
    ocrFile.value = null;
  } catch (err: unknown) {
    $q.notify({
      type: 'negative',
      message: (err as { response?: { data?: { detail?: string } } }).response?.data?.detail || 'Failed to add items',
    });
  } finally {
    addingOcrItems.value = false;
  }
};

// Add keyboard shortcut handler
const handleKeyPress = (event: KeyboardEvent) => {
  // Focus item name input when pressing 'n'
  if (event.key === 'n' && !event.ctrlKey && !event.metaKey) {
    event.preventDefault();
    itemNameInput.value?.focus();
  }
};

// Add confirmation dialog handlers
const confirmUpdateItem = (item: Item) => {
  confirmDialogMessage.value = `Are you sure you want to mark "${item.name}" as ${item.is_complete ? 'complete' : 'incomplete'}?`;
  pendingAction.value = () => updateItem(item);
  showConfirmDialog.value = true;
};

const confirmDeleteItem = (item: Item) => {
  confirmDialogMessage.value = `Are you sure you want to delete "${item.name}"?`;
  pendingAction.value = () => deleteItem(item);
  showConfirmDialog.value = true;
};

const handleConfirmedAction = async () => {
  if (pendingAction.value) {
    await pendingAction.value();
    pendingAction.value = null;
  }
  showConfirmDialog.value = false;
};

// Add delete item function
const deleteItem = async (item: Item) => {
  item.deleting = true;
  try {
    await apiClient.delete(
      API_ENDPOINTS.LISTS.ITEM(String(list.value.id), String(item.id))
    );
    const index = list.value.items.findIndex((i) => i.id === item.id);
    if (index !== -1) {
      list.value.items.splice(index, 1);
    }
  } catch (err: unknown) {
    $q.notify({
      type: 'negative',
      message: (err as Error).message || 'Failed to delete item',
    });
  } finally {
    item.deleting = false;
  }
};

// Add keyboard event listeners
onMounted(() => {
  console.log('Component mounted, route params:', route.params);
  if (!route.params.id) {
    console.error('No list ID found in route params');
    error.value = 'No list ID provided';
    return;
  }
  void fetchListDetails().then(() => {
    startPolling();
  });
  window.addEventListener('keydown', handleKeyPress);
});

onUnmounted(() => {
  stopPolling();
  window.removeEventListener('keydown', handleKeyPress);
});
</script>

<style scoped>
.text-strike {
  text-decoration: line-through;
  opacity: 0.7;
}

/* Add transition for item updates */
.q-item {
  transition: all 0.3s ease;
}

.q-item.updating {
  opacity: 0.7;
  pointer-events: none;
}
</style>
