<script lang="ts" setup>
import { ref } from 'vue'
import { Link, useForm, usePage, router } from '@inertiajs/vue3'
import type { LoginHistoryEntry, SharedPageProps, TrustedDevice } from '@/types'

interface Props {
  twoFactorEnabled: boolean
  loginHistories: LoginHistoryEntry[]
  trustedDevices: TrustedDevice[]
}

const props = defineProps<Props>()

function formatDateTime(dateStr: string): string {
  const date = new Date(dateStr)
  return date.toLocaleDateString('en-US', {
    month: 'short',
    day: '2-digit',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  })
}

function formatLocation(entry: LoginHistoryEntry): string {
  const parts = [entry.location_city, entry.location_country].filter(Boolean)
  return parts.length > 0 ? parts.join(', ') : '-'
}

function formatBrowserOs(entry: LoginHistoryEntry): string {
  const parts = [entry.browser, entry.os].filter(Boolean)
  return parts.length > 0 ? parts.join(' / ') : 'Unknown'
}

function formatRelativeTime(dateStr: string): string {
  const date = new Date(dateStr)
  const now = new Date()
  const diffMs = now.getTime() - date.getTime()
  const diffMins = Math.floor(diffMs / 60000)
  if (diffMins < 1) return 'Just now'
  if (diffMins < 60) return `${diffMins}m ago`
  const diffHours = Math.floor(diffMins / 60)
  if (diffHours < 24) return `${diffHours}h ago`
  const diffDays = Math.floor(diffHours / 24)
  if (diffDays < 30) return `${diffDays}d ago`
  return formatDateTime(dateStr)
}

function daysUntilExpiry(dateStr: string): number {
  const expires = new Date(dateStr)
  const now = new Date()
  return Math.max(0, Math.ceil((expires.getTime() - now.getTime()) / 86400000))
}

const page = usePage<SharedPageProps>()

const isCurrentPasswordVisible = ref<boolean>(false)
const isNewPasswordVisible = ref<boolean>(false)
const isConfirmPasswordVisible = ref<boolean>(false)

const passwordForm = useForm({
  current_password: '',
  password: '',
  password_confirmation: '',
})

const submitPassword = (): void => {
  passwordForm.put('/profile/password', {
    preserveScroll: true,
    onSuccess: () => {
      passwordForm.reset()
    },
  })
}

const resetPasswordForm = (): void => {
  passwordForm.reset()
  passwordForm.clearErrors()
}

const passwordRequirements: string[] = [
  'Minimum 8 characters long - the more, the better',
  'At least one lowercase character',
  'At least one uppercase character',
  'At least one number, symbol, or whitespace character',
]

// Two-factor authentication
const enabling = ref<boolean>(false)
const confirming = ref<boolean>(false)
const disabling = ref<boolean>(false)
const qrCode = ref<string>('')
const recoveryCodes = ref<string[]>([])

const confirmationForm = useForm({
  code: '',
})

const enableTwoFactor = (): void => {
  enabling.value = true
  router.post('/user/two-factor-authentication', {}, {
    preserveScroll: true,
    onSuccess: () => {
      confirming.value = true
      showQrCode()
      showRecoveryCodes()
    },
    onFinish: () => {
      enabling.value = false
    },
  })
}

const showQrCode = (): void => {
  fetch('/user/two-factor-qr-code')
    .then(r => r.json())
    .then((data: { svg: string }) => { qrCode.value = data.svg })
}

const showRecoveryCodes = (): void => {
  fetch('/user/two-factor-recovery-codes')
    .then(r => r.json())
    .then((data: string[]) => { recoveryCodes.value = data })
}

const confirmTwoFactor = (): void => {
  confirmationForm.post('/user/confirmed-two-factor-authentication', {
    preserveScroll: true,
    onSuccess: () => {
      confirming.value = false
    },
  })
}

const disableTwoFactor = (): void => {
  disabling.value = true
  router.delete('/user/two-factor-authentication', {
    preserveScroll: true,
    onSuccess: () => {
      qrCode.value = ''
      recoveryCodes.value = []
    },
    onFinish: () => {
      disabling.value = false
    },
  })
}

// Trusted device management
const removingDeviceId = ref<number | null>(null)
const removingAllDevices = ref<boolean>(false)

const removeTrustedDevice = (deviceId: number): void => {
  removingDeviceId.value = deviceId
  router.delete(`/profile/trusted-devices/${deviceId}`, {
    preserveScroll: true,
    onFinish: () => {
      removingDeviceId.value = null
    },
  })
}

const removeAllTrustedDevices = (): void => {
  removingAllDevices.value = true
  router.delete('/profile/trusted-devices', {
    preserveScroll: true,
    onFinish: () => {
      removingAllDevices.value = false
    },
  })
}

// Logout other sessions
const showLogoutSessionsDialog = ref<boolean>(false)
const sessionForm = useForm({
  password: '',
})

const logoutOtherSessions = (): void => {
  sessionForm.delete('/profile/sessions', {
    preserveScroll: true,
    onSuccess: () => {
      showLogoutSessionsDialog.value = false
      sessionForm.reset()
    },
  })
}
</script>

<template>
  <VRow>
    <!-- Change Password -->
    <VCol cols="12">
      <VCard title="Change Password">
        <VForm @submit.prevent="submitPassword">
          <VCardText class="pt-0">
            <VRow>
              <VCol
                cols="12"
                md="6"
              >
                <VTextField
                  v-model="passwordForm.current_password"
                  :type="isCurrentPasswordVisible ? 'text' : 'password'"
                  :append-inner-icon="isCurrentPasswordVisible ? 'tabler-eye-off' : 'tabler-eye'"
                  label="Current Password"
                  autocomplete="current-password"
                  placeholder="............"
                  :error-messages="passwordForm.errors.current_password ? [passwordForm.errors.current_password] : []"
                  @click:append-inner="isCurrentPasswordVisible = !isCurrentPasswordVisible"
                />
              </VCol>
            </VRow>

            <VRow>
              <VCol
                cols="12"
                md="6"
              >
                <VTextField
                  v-model="passwordForm.password"
                  :type="isNewPasswordVisible ? 'text' : 'password'"
                  :append-inner-icon="isNewPasswordVisible ? 'tabler-eye-off' : 'tabler-eye'"
                  label="New Password"
                  autocomplete="new-password"
                  placeholder="............"
                  :error-messages="passwordForm.errors.password ? [passwordForm.errors.password] : []"
                  @click:append-inner="isNewPasswordVisible = !isNewPasswordVisible"
                />
              </VCol>

              <VCol
                cols="12"
                md="6"
              >
                <VTextField
                  v-model="passwordForm.password_confirmation"
                  :type="isConfirmPasswordVisible ? 'text' : 'password'"
                  :append-inner-icon="isConfirmPasswordVisible ? 'tabler-eye-off' : 'tabler-eye'"
                  label="Confirm New Password"
                  autocomplete="new-password"
                  placeholder="............"
                  :error-messages="passwordForm.errors.password_confirmation ? [passwordForm.errors.password_confirmation] : []"
                  @click:append-inner="isConfirmPasswordVisible = !isConfirmPasswordVisible"
                />
              </VCol>
            </VRow>
          </VCardText>

          <VCardText>
            <h6 class="text-h6 text-medium-emphasis mb-4">
              Password Requirements:
            </h6>

            <VList class="card-list">
              <VListItem
                v-for="item in passwordRequirements"
                :key="item"
                :title="item"
                class="text-medium-emphasis"
              >
                <template #prepend>
                  <VIcon
                    size="10"
                    icon="tabler-circle-filled"
                  />
                </template>
              </VListItem>
            </VList>
          </VCardText>

          <VCardText class="d-flex flex-wrap gap-4">
            <VBtn
              type="submit"
              :loading="passwordForm.processing"
              :disabled="passwordForm.processing"
            >
              Save changes
            </VBtn>

            <VBtn
              color="secondary"
              variant="tonal"
              @click="resetPasswordForm"
            >
              Reset
            </VBtn>
          </VCardText>
        </VForm>
      </VCard>
    </VCol>

    <!-- Two-Factor Authentication -->
    <VCol cols="12">
      <VCard title="Two-Factor Authentication">
        <VCardText>
          <div v-if="!twoFactorEnabled && !confirming">
            <h5 class="text-h5 text-medium-emphasis mb-4">
              Two-factor authentication is not enabled yet.
            </h5>
            <p class="mb-6">
              Two-factor authentication adds an additional layer of security to your account by
              requiring more than just a password to log in. You will need to enter a code from your
              authenticator app each time you sign in.
            </p>

            <VBtn
              :loading="enabling"
              :disabled="enabling"
              @click="enableTwoFactor"
            >
              Enable two-factor authentication
            </VBtn>
          </div>

          <!-- QR Code confirmation step -->
          <div v-if="confirming">
            <div class="text-body-2 text-medium-emphasis mb-4">
              Scan this QR code with your authenticator app, then enter the code below to confirm.
            </div>

            <!-- eslint-disable-next-line vue/no-v-html -->
            <div
              v-if="qrCode"
              v-html="qrCode"
              class="mb-4 d-inline-block pa-4 rounded"
              style="background: white;"
            />

            <VForm
              @submit.prevent="confirmTwoFactor"
              style="max-width: 300px;"
            >
              <VTextField
                v-model="confirmationForm.code"
                label="Confirmation Code"
                type="text"
                inputmode="numeric"
                placeholder="000000"
                :error-messages="confirmationForm.errors.code ? [confirmationForm.errors.code] : []"
                class="mb-4"
              />

              <VBtn
                type="submit"
                :loading="confirmationForm.processing"
                :disabled="confirmationForm.processing"
              >
                Confirm
              </VBtn>
            </VForm>
          </div>

          <!-- Recovery codes -->
          <div v-if="recoveryCodes.length > 0 && !confirming">
            <div class="text-subtitle-2 font-weight-bold mb-2">
              Recovery Codes
            </div>
            <div class="text-body-2 text-medium-emphasis mb-3">
              Store these codes in a safe place. They can be used to access your account if you lose your authenticator device.
            </div>
            <VSheet
              rounded
              color="surface-variant"
              class="pa-4 font-weight-medium"
              style="font-family: monospace;"
            >
              <div
                v-for="code in recoveryCodes"
                :key="code"
              >
                {{ code }}
              </div>
            </VSheet>
          </div>

          <!-- 2FA enabled state -->
          <div v-if="twoFactorEnabled && !confirming">
            <VAlert
              type="success"
              variant="tonal"
              class="mb-4"
            >
              Two-factor authentication is enabled.
            </VAlert>

            <VBtn
              color="error"
              variant="tonal"
              :loading="disabling"
              :disabled="disabling"
              @click="disableTwoFactor"
            >
              Disable Two-Factor Authentication
            </VBtn>
          </div>
        </VCardText>
      </VCard>
    </VCol>

    <!-- Trusted Devices -->
    <VCol cols="12">
      <VCard>
        <VCardTitle class="d-flex align-center justify-space-between">
          <div class="d-flex align-center gap-2">
            <VIcon icon="tabler-device-desktop-check" size="22" />
            <span>Trusted Devices</span>
          </div>
          <VBtn
            v-if="props.trustedDevices.length > 0"
            variant="text"
            color="error"
            size="small"
            :loading="removingAllDevices"
            @click="removeAllTrustedDevices"
          >
            Remove All
          </VBtn>
        </VCardTitle>
        <VDivider />
        <VCardText v-if="props.trustedDevices.length === 0" class="text-center py-8">
          <VIcon icon="tabler-device-desktop-off" size="40" color="disabled" class="mb-2" />
          <div class="text-body-1 text-medium-emphasis">
            No trusted devices. When you check "Trust this device" during two-factor authentication, the device will appear here.
          </div>
        </VCardText>
        <VList v-else lines="two">
          <VListItem
            v-for="device in props.trustedDevices"
            :key="device.id"
          >
            <template #prepend>
              <VAvatar color="primary" variant="tonal">
                <VIcon icon="tabler-device-desktop" />
              </VAvatar>
            </template>
            <VListItemTitle>{{ device.device_name || 'Unknown Device' }}</VListItemTitle>
            <VListItemSubtitle>
              {{ device.ip_address }}
              <span class="mx-1">--</span>
              Last used {{ device.last_used_at ? formatRelativeTime(device.last_used_at) : 'Never' }}
              <span class="mx-1">--</span>
              Expires in {{ daysUntilExpiry(device.expires_at) }} days
            </VListItemSubtitle>
            <template #append>
              <VBtn
                icon="tabler-x"
                variant="text"
                color="error"
                size="small"
                :loading="removingDeviceId === device.id"
                @click="removeTrustedDevice(device.id)"
              />
            </template>
          </VListItem>
        </VList>
      </VCard>
    </VCol>

    <!-- Active Sessions -->
    <VCol cols="12">
      <VCard>
        <VCardTitle class="d-flex align-center gap-2">
          <VIcon icon="tabler-logout" size="22" />
          <span>Active Sessions</span>
        </VCardTitle>
        <VDivider />
        <VCardText>
          <p class="text-body-2 text-medium-emphasis mb-4">
            If necessary, you may log out of all of your other browser sessions across all of your devices.
            If you feel your account has been compromised, you should also change your password.
          </p>
          <VBtn
            color="error"
            variant="tonal"
            @click="showLogoutSessionsDialog = true"
          >
            <VIcon icon="tabler-logout" start />
            Log Out Other Sessions
          </VBtn>
        </VCardText>
      </VCard>
    </VCol>

    <!-- Recent Login History -->
    <VCol cols="12">
      <VCard>
        <VCardTitle class="d-flex align-center justify-space-between">
          <div class="d-flex align-center gap-2">
            <VIcon icon="tabler-history" size="22" />
            <span>Recent Login History</span>
          </div>
          <Link href="/login-history">
            <VBtn variant="text" color="primary" size="small">
              View All
              <VIcon icon="tabler-arrow-right" end size="16" />
            </VBtn>
          </Link>
        </VCardTitle>
        <VDivider />
        <VCardText v-if="props.loginHistories.length === 0" class="text-center py-8">
          <VIcon icon="tabler-history-off" size="40" color="disabled" class="mb-2" />
          <div class="text-body-1 text-medium-emphasis">
            No login history yet.
          </div>
        </VCardText>
        <VTable v-else density="comfortable" hover>
          <thead>
            <tr>
              <th>BROWSER / OS</th>
              <th>DEVICE</th>
              <th>LOCATION</th>
              <th>IP ADDRESS</th>
              <th>TIME</th>
              <th>STATUS</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="entry in props.loginHistories" :key="entry.id">
              <td class="text-body-2">
                {{ formatBrowserOs(entry) }}
              </td>
              <td class="text-body-2">
                {{ entry.device_type ?? '-' }}
              </td>
              <td class="text-body-2">
                {{ formatLocation(entry) }}
              </td>
              <td class="text-body-2 text-medium-emphasis">
                {{ entry.ip_address }}
              </td>
              <td class="text-body-2 text-medium-emphasis">
                {{ formatDateTime(entry.created_at) }}
              </td>
              <td>
                <VChip
                  :color="entry.success ? 'success' : 'error'"
                  size="small"
                  variant="tonal"
                >
                  {{ entry.success ? 'Success' : 'Failed' }}
                </VChip>
              </td>
            </tr>
          </tbody>
        </VTable>
      </VCard>
    </VCol>

    <!-- Logout Other Sessions Dialog -->
    <VDialog v-model="showLogoutSessionsDialog" max-width="500">
      <VCard>
        <VCardTitle class="d-flex align-center gap-2">
          <VIcon icon="tabler-logout" color="warning" />
          Log Out Other Sessions
        </VCardTitle>
        <VCardText>
          <p class="text-body-2 text-medium-emphasis mb-4">
            Please enter your password to confirm you would like to log out of your other browser sessions.
          </p>
          <VTextField
            v-model="sessionForm.password"
            type="password"
            label="Password"
            autocomplete="current-password"
            placeholder="Enter your password"
            :error-messages="sessionForm.errors.password ? [sessionForm.errors.password] : []"
          />
        </VCardText>
        <VCardActions class="justify-end">
          <VBtn @click="showLogoutSessionsDialog = false; sessionForm.reset(); sessionForm.clearErrors()">
            Cancel
          </VBtn>
          <VBtn
            color="error"
            :loading="sessionForm.processing"
            :disabled="!sessionForm.password || sessionForm.processing"
            @click="logoutOtherSessions"
          >
            Log Out Other Sessions
          </VBtn>
        </VCardActions>
      </VCard>
    </VDialog>
  </VRow>
</template>

<style lang="scss" scoped>
.card-list {
  --v-card-list-gap: 16px;
}
</style>
