<template>
  <q-page padding>
    <div class="q-mb-md row justify-between items-center">
      <div class="text-h4">
        Passkey Management
      </div>
      <div>
        <q-btn
          label="Identify Passkey"
          color="secondary"
          class="q-mx-md q-mt-md"
          @click="handleIdentify"
          :loading="identifyLoading"
          :disable="identifyLoading || !isLoggedIn"
          outline
        />
        <q-btn
          label="Register New Passkey"
          color="primary"
          class="q-mx-md q-mt-md"
          @click="handleRegister"
          :loading="registerLoading"
          :disable="registerLoading || !isLoggedIn"
          outline
        />
      </div>
    </div>

    <!-- Passkey List Section -->
    <q-card-section>
      <h5>Your Registered Passkeys</h5>
      <q-list
        bordered
        separator
        v-if="passkeys.length > 0 && !fetchLoading"
      >
        <q-item v-if="registerSuccessMessage || registerErrorMessage">
          <div
            v-if="registerSuccessMessage"
            class="text-positive q-mt-md"
          >
            {{ registerSuccessMessage }}
          </div>
          <div
            v-if="registerErrorMessage"
            class="text-negative q-mt-md"
          >
            {{ registerErrorMessage }}
          </div>
        </q-item>
        <q-item
          v-for="passkey in passkeys"
          :key="passkey.credentialID"
          :class="{ 'bg-info text-h6': identifiedPasskeyId === passkey.credentialID }" 
        >
          <q-item-section>
            <q-item-label>Passkey ID: {{ passkey.credentialID }} </q-item-label>
            <q-item-label
              caption
              v-if="identifiedPasskeyId === passkey.credentialID"
            >
              Verified just now!
            </q-item-label>
            <!-- <q-item-label caption>Registered: {{ new Date(passkey.createdAt).toLocaleDateString() }}</q-item-label> -->
          </q-item-section>

          <q-item-section
            side
            class="row no-wrap items-center"
          >
            <!-- Delete Button -->
            <q-btn
              flat
              dense
              round
              color="negative"
              icon="delete"
              @click="handleDelete(passkey.credentialID)"
              :loading="deleteLoading === passkey.credentialID"
              :disable="!!deleteLoading || !!identifyLoading"
            />
          </q-item-section>
        </q-item>
      </q-list>
      <div
        v-else-if="fetchLoading"
        class="q-mt-md"
      >
        Loading passkeys...
      </div>
      <div
        v-else
        class="q-mt-md"
      >
        You have no passkeys registered yet.
      </div>

      <div
        v-if="fetchErrorMessage"
        class="text-negative q-mt-md"
      >
        {{ fetchErrorMessage }}
      </div>
      <div
        v-if="deleteSuccessMessage"
        class="text-positive q-mt-md"
      >
        {{ deleteSuccessMessage }}
      </div>
      <div
        v-if="deleteErrorMessage"
        class="text-negative q-mt-md"
      >
        {{ deleteErrorMessage }}
      </div>
      <div
        v-if="identifyErrorMessage"
        class="text-negative q-mt-md"
      >
        {{ identifyErrorMessage }}
      </div>
    </q-card-section>
  </q-page>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue';
import { startRegistration, startAuthentication } from '@simplewebauthn/browser'; // Import startAuthentication
import axios from 'boot/axios';
import { useAuthStore } from 'stores/auth';

const registerLoading = ref(false);
const registerErrorMessage = ref('');
const registerSuccessMessage = ref('');
const fetchLoading = ref(false);
const fetchErrorMessage = ref('');
const deleteLoading = ref(null);
const deleteErrorMessage = ref('');
const deleteSuccessMessage = ref('');
const identifyLoading = ref(null); // Store the ID of the passkey being identified
const identifyErrorMessage = ref('');
const identifiedPasskeyId = ref(null); // Store the ID of the successfully identified passkey

const authStore = useAuthStore();
const passkeys = ref([]); // To store the list of passkeys

// Computed properties to get state from the store
const isLoggedIn = computed(() => authStore.isAuthenticated);
const username = computed(() => authStore.user?.username);

// Fetch existing passkeys
async function fetchPasskeys() 
{
  if (!isLoggedIn.value) return;
  fetchLoading.value = true;
  fetchErrorMessage.value = '';
  deleteSuccessMessage.value = ''; // Clear delete messages on refresh
  deleteErrorMessage.value = '';
  identifyErrorMessage.value = ''; // Clear identify message
  identifiedPasskeyId.value = null; // Clear identified key
  try 
  {
    const response = await axios.get('/api/auth/passkeys');
    passkeys.value = response.data || [];
  }
  catch (error) 
  {
    console.error('Error fetching passkeys:', error);
    fetchErrorMessage.value = error.response?.data?.error || 'Failed to load passkeys.';
    passkeys.value = []; // Clear passkeys on error
  }
  finally 
  {
    fetchLoading.value = false;
  }
}

// Check auth status and fetch passkeys on component mount
onMounted(async() => 
{
  let initialAuthError = '';
  if (!authStore.isAuthenticated) 
  {
    await authStore.checkAuthStatus();
    if (authStore.error) 
    {
      initialAuthError = `Authentication error: ${authStore.error}`;
    }
  }
  if (!isLoggedIn.value) 
  {
    // Use register error message ref for consistency if login is required first
    registerErrorMessage.value = initialAuthError || 'You must be logged in to manage passkeys.';
  }
  else 
  {
    fetchPasskeys(); // Fetch passkeys if logged in
  }
});

async function handleRegister() 
{
  if (!isLoggedIn.value || !username.value) 
  {
    registerErrorMessage.value = 'User not authenticated.';
    return;
  }
  registerLoading.value = true;
  registerErrorMessage.value = '';
  registerSuccessMessage.value = '';
  deleteSuccessMessage.value = ''; // Clear other messages
  deleteErrorMessage.value = '';
  identifyErrorMessage.value = '';
  identifiedPasskeyId.value = null;

  try 
  {
    // 1. Get options from server
    const optionsRes = await axios.post('/api/auth/generate-registration-options', {
      username: username.value, // Use username from store
    });
    const options = optionsRes.data;

    // 2. Start registration ceremony in browser
    const regResp = await startRegistration(options);

    // 3. Send response to server for verification
    const verificationRes = await axios.post('/api/auth/verify-registration', {
      registrationResponse: regResp,
    });

    if (verificationRes.data.verified) 
    {
      registerSuccessMessage.value = 'New passkey registered successfully!';
      fetchPasskeys(); // Refresh the list of passkeys
    }
    else 
    {
      registerErrorMessage.value = 'Passkey verification failed.';
    }
  }
  catch (error) 
  {
    console.error('Registration error:', error);
    const message = error.response?.data?.error || error.message || 'An unknown error occurred during registration.';
    // Handle specific simplewebauthn errors
    if (error.name === 'InvalidStateError') 
    {
      registerErrorMessage.value = 'Authenticator may already be registered.';
    }
    else if (error.name === 'NotAllowedError') 
    {
      registerErrorMessage.value = 'Registration ceremony was cancelled or timed out.';
    }
    else if (error.response?.status === 409) 
    {
      registerErrorMessage.value = 'This passkey seems to be registered already.';
    }
    else 
    {
      registerErrorMessage.value = `Registration failed: ${message}`;
    }
  }
  finally 
  {
    registerLoading.value = false;
  }
}


// Handle deleting a passkey
async function handleDelete(credentialID) 
{
  if (!credentialID) return;

  // Optional: Add a confirmation dialog here
  // if (!confirm('Are you sure you want to delete this passkey?')) {
  //   return;
  // }

  deleteLoading.value = credentialID; // Set loading state for the specific button
  deleteErrorMessage.value = '';
  deleteSuccessMessage.value = '';
  registerSuccessMessage.value = ''; // Clear other messages
  registerErrorMessage.value = '';
  identifyErrorMessage.value = '';
  identifiedPasskeyId.value = null;

  try 
  {
    await axios.delete(`/api/auth/passkeys/${credentialID}`);
    deleteSuccessMessage.value = 'Passkey deleted successfully.';
    fetchPasskeys(); // Refresh the list
  }
  catch (error) 
  {
    console.error('Error deleting passkey:', error);
    deleteErrorMessage.value = error.response?.data?.error || 'Failed to delete passkey.';
  }
  finally 
  {
    deleteLoading.value = null; // Clear loading state
  }
}

// Handle identifying a passkey
async function handleIdentify() 
{
  if (!isLoggedIn.value) 
  {
    identifyErrorMessage.value = 'You must be logged in.';
    return;
  }

  identifyLoading.value = true;
  identifyErrorMessage.value = '';
  identifiedPasskeyId.value = null; // Reset identified key
  // Clear other messages
  registerSuccessMessage.value = '';
  registerErrorMessage.value = '';
  deleteSuccessMessage.value = '';
  deleteErrorMessage.value = '';

  try 
  {
    // 1. Get authentication options from the server
    // We don't need to send username as the server should use the session
    const optionsRes = await axios.post('/api/auth/generate-authentication-options', {}); // Send empty body
    const options = optionsRes.data;

    // Optionally filter options to only allow the specific key if needed, but usually not necessary for identification
    // options.allowCredentials = options.allowCredentials?.filter(cred => cred.id === credentialIDToIdentify);

    // 2. Start authentication ceremony in the browser
    const authResp = await startAuthentication(options);

    // 3. If successful, the response contains the ID of the key used
    identifiedPasskeyId.value = authResp.id;
    console.log('Identified Passkey ID:', identifiedPasskeyId.value);

    // Optional: Add a small delay before clearing the highlight
    setTimeout(() => 
    {
      // Only clear if it's still the same identified key
      if (identifiedPasskeyId.value === authResp.id) 
      { 
        identifiedPasskeyId.value = null;
      }
    }, 5000); // Clear highlight after 5 seconds

  }
  catch (error) 
  {
    console.error('Identification error:', error);
    identifiedPasskeyId.value = null;
    if (error.name === 'NotAllowedError') 
    {
      identifyErrorMessage.value = 'Identification ceremony was cancelled or timed out.';
    }
    else 
    {
      identifyErrorMessage.value = error.response?.data?.error || error.message || 'Failed to identify passkey.';
    }
  }
  finally 
  {
    identifyLoading.value = null; // Clear loading state
  }
}

</script>