<template>
  <div class="view">
    <EntityEditForm
      entityLabel="User Profile"
      :fields="fields"
      :initialData="initialData"
      :isEdit="true"
      :loading="loading"
      :error="errorMsg"
      :title="'User Profile'"
      @submit="handleSubmit"
      @cancel="router.back"
      @add-image="onAddImage"
    >
      <template #custom-field-email="{ modelValue }">
        <div class="email-actions">
          <input id="email" type="email" :value="modelValue" disabled class="readonly-input" />
          <button type="button" class="btn-link btn-link-space" @click="goToChangeParentPin">
            Change Parent PIN
          </button>
          <button
            type="button"
            class="btn-link btn-link-space"
            @click="resetPassword"
            :disabled="resetting"
          >
            Change Password
          </button>
          <button type="button" class="btn-link btn-link-space" @click="openDeleteWarning">
            Delete My Account
          </button>
        </div>
      </template>
    </EntityEditForm>
    <div v-if="errorMsg" class="error-message" aria-live="polite">{{ errorMsg }}</div>
    <ModalDialog
      v-if="showModal"
      :title="modalTitle"
      :subtitle="modalSubtitle"
      @close="handlePasswordModalClose"
    >
      <div class="modal-message">{{ modalMessage }}</div>
      <div class="modal-actions" v-if="!resetting">
        <button class="btn btn-primary" @click="handlePasswordModalClose">OK</button>
      </div>
    </ModalDialog>

    <!-- Delete Account Warning Modal -->
    <ModalDialog v-if="showDeleteWarning" title="Delete Your Account?" @close="closeDeleteWarning">
      <div class="modal-message">
        This will permanently delete your account and all associated data. This action cannot be
        undone.
      </div>
      <div class="form-group" style="margin-top: 1rem">
        <label for="confirmEmail">Type your email address to confirm:</label>
        <input
          id="confirmEmail"
          v-model="confirmEmail"
          type="email"
          class="email-confirm-input"
          placeholder="Enter your email"
          :disabled="deletingAccount"
        />
      </div>
      <div class="modal-actions">
        <button class="btn btn-secondary" @click="closeDeleteWarning" :disabled="deletingAccount">
          Cancel
        </button>
        <button
          class="btn btn-danger"
          @click="confirmDeleteAccount"
          :disabled="!isEmailValid(confirmEmail) || deletingAccount"
        >
          {{ deletingAccount ? 'Deleting...' : 'Delete' }}
        </button>
      </div>
    </ModalDialog>

    <!-- Delete Account Success Modal -->
    <ModalDialog v-if="showDeleteSuccess" title="Account Deleted">
      <div class="modal-message">
        Your account has been marked for deletion. You will now be signed out.
      </div>
      <div class="modal-actions">
        <button class="btn btn-primary" @click="handleDeleteSuccess">OK</button>
      </div>
    </ModalDialog>

    <!-- Delete Account Error Modal -->
    <ModalDialog v-if="showDeleteError" title="Error" @close="closeDeleteError">
      <div class="modal-message">{{ deleteErrorMessage }}</div>
      <div class="modal-actions">
        <button class="btn btn-primary" @click="closeDeleteError">Close</button>
      </div>
    </ModalDialog>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import EntityEditForm from '../shared/EntityEditForm.vue'
import ModalDialog from '../shared/ModalDialog.vue'
import { parseErrorResponse, isEmailValid } from '@/common/api'
import { ALREADY_MARKED } from '@/common/errorCodes'
import { logoutUser, suppressForceLogout } from '@/stores/auth'
import '@/assets/styles.css'

const router = useRouter()
const loading = ref(false)
const errorMsg = ref('')
const resetting = ref(false)
const localImageFile = ref<File | null>(null)
const showModal = ref(false)
const modalTitle = ref('')
const modalSubtitle = ref('')
const modalMessage = ref('')

// Delete account modal state
const showDeleteWarning = ref(false)
const confirmEmail = ref('')
const deletingAccount = ref(false)
const showDeleteSuccess = ref(false)
const showDeleteError = ref(false)
const deleteErrorMessage = ref('')

const initialData = ref<{
  image_id: string | null
  first_name: string
  last_name: string
  email: string
}>({
  image_id: null,
  first_name: '',
  last_name: '',
  email: '',
})

const fields: Array<{
  name: string
  label: string
  type: 'image' | 'text' | 'custom'
  imageType?: number
  required?: boolean
  maxlength?: number
}> = [
  { name: 'image_id', label: 'Image', type: 'image', imageType: 1 },
  { name: 'first_name', label: 'First Name', type: 'text', required: true, maxlength: 64 },
  { name: 'last_name', label: 'Last Name', type: 'text', required: true, maxlength: 64 },
  { name: 'email', label: 'Email Address', type: 'custom' },
]

onMounted(async () => {
  loading.value = true
  try {
    const res = await fetch('/api/user/profile')
    if (!res.ok) throw new Error('Failed to load profile')
    const data = await res.json()
    initialData.value = {
      image_id: data.image_id || null,
      first_name: data.first_name || '',
      last_name: data.last_name || '',
      email: data.email || '',
    }
  } catch {
    errorMsg.value = 'Could not load user profile.'
  } finally {
    loading.value = false
  }
})

function onAddImage({ id, file }: { id: string; file: File }) {
  if (id === 'local-upload') {
    localImageFile.value = file
  } else {
    localImageFile.value = null
    initialData.value.image_id = id
  }
}

function handleSubmit(form: {
  image_id: string | null
  first_name: string
  last_name: string
  email: string
}) {
  errorMsg.value = ''
  loading.value = true

  // Handle image upload if local file
  let imageId = form.image_id
  if (imageId === 'local-upload' && localImageFile.value) {
    const formData = new FormData()
    formData.append('file', localImageFile.value)
    formData.append('type', '1')
    formData.append('permanent', 'true')
    fetch('/api/image/upload', {
      method: 'POST',
      body: formData,
    })
      .then(async (resp) => {
        if (!resp.ok) throw new Error('Image upload failed')
        const data = await resp.json()
        imageId = data.id
        // Now update profile
        return updateProfile({
          ...form,
          image_id: imageId,
        })
      })
      .catch(() => {
        errorMsg.value = 'Failed to upload image.'
        loading.value = false
      })
  } else {
    updateProfile(form)
  }
}

async function updateProfile(form: {
  image_id: string | null
  first_name: string
  last_name: string
  email: string
}) {
  fetch('/api/user/profile', {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      first_name: form.first_name,
      last_name: form.last_name,
      image_id: form.image_id,
    }),
  })
    .then(async (res) => {
      if (!res.ok) throw new Error('Failed to update profile')
      // Update initialData to reflect the saved state
      initialData.value = { ...form }
      modalTitle.value = 'Profile Updated'
      modalSubtitle.value = ''
      modalMessage.value = 'Your profile was updated successfully.'
      showModal.value = true
    })
    .catch(() => {
      errorMsg.value = 'Failed to update profile.'
    })
    .finally(() => {
      loading.value = false
    })
}

async function handlePasswordModalClose() {
  const wasProfileUpdate = modalTitle.value === 'Profile Updated'
  showModal.value = false
  if (wasProfileUpdate) {
    router.back()
  }
}

async function resetPassword() {
  // Show modal immediately with loading message
  modalTitle.value = 'Change Password'
  modalMessage.value = 'Sending password change email...'
  modalSubtitle.value = ''
  showModal.value = true
  resetting.value = true
  errorMsg.value = ''
  try {
    const res = await fetch('/api/auth/request-password-reset', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email: initialData.value.email }),
    })
    if (!res.ok) throw new Error('Failed to send reset email')
    modalTitle.value = 'Password Change Email Sent'
    modalMessage.value =
      'If this email is registered, you will receive a password change link shortly.'
  } catch {
    modalTitle.value = 'Password Change Failed'
    modalMessage.value = 'Failed to send password change email.'
  } finally {
    resetting.value = false
  }
}

function goToChangeParentPin() {
  router.push({ name: 'ParentPinSetup' })
}

function openDeleteWarning() {
  confirmEmail.value = ''
  showDeleteWarning.value = true
}

function closeDeleteWarning() {
  showDeleteWarning.value = false
  confirmEmail.value = ''
}

async function confirmDeleteAccount() {
  if (!isEmailValid(confirmEmail.value)) return

  // Set flag before the request so it's guaranteed to be set
  // before the force_logout SSE event can arrive on this tab
  suppressForceLogout.value = true
  deletingAccount.value = true
  try {
    const res = await fetch('/api/user/mark-for-deletion', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email: confirmEmail.value }),
    })

    if (!res.ok) {
      suppressForceLogout.value = false
      const { msg, code } = await parseErrorResponse(res)
      let errorMessage = msg
      if (code === ALREADY_MARKED) {
        errorMessage = 'This account is already marked for deletion.'
      }
      deleteErrorMessage.value = errorMessage
      showDeleteWarning.value = false
      showDeleteError.value = true
      return
    }

    // Success — suppressForceLogout is already set; show confirmation modal
    showDeleteWarning.value = false
    showDeleteSuccess.value = true
  } catch {
    suppressForceLogout.value = false
    deleteErrorMessage.value = 'Network error. Please try again.'
    showDeleteWarning.value = false
    showDeleteError.value = true
  } finally {
    deletingAccount.value = false
  }
}

function handleDeleteSuccess() {
  showDeleteSuccess.value = false
  // Call logout API to clear server cookies
  fetch('/api/auth/logout', {
    method: 'POST',
    credentials: 'include',
  }).finally(() => {
    // Clear client-side auth and redirect, regardless of logout response
    logoutUser()
    router.push('/')
  })
}

function closeDeleteError() {
  showDeleteError.value = false
  deleteErrorMessage.value = ''
}
</script>

<style scoped>
.view {
  max-width: 400px;
  margin: 0 auto;
  background: var(--form-bg);
  border-radius: 12px;
  box-shadow: 0 4px 24px var(--form-shadow);
  padding: 2rem 2.2rem 1.5rem 2.2rem;
}
/* ...existing styles... */
.email-actions {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.success-message {
  color: var(--success, #16a34a);
  font-size: 1rem;
}
.error-message {
  color: var(--error, #e53e3e);
  font-size: 0.98rem;
  margin-top: 0.4rem;
}
.readonly-input {
  width: 100%;
  padding: 0.6rem;
  border-radius: 7px;
  border: 1px solid var(--form-input-border, #e6e6e6);
  font-size: 1rem;
  background: var(--form-input-bg, #f5f5f5);
  color: var(--form-label, #888);
  box-sizing: border-box;
}

.btn-danger-link {
  background: none;
  border: none;
  color: var(--error, #e53e3e);
  font-size: 0.95rem;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
  margin-top: 0.25rem;
  align-self: flex-start;
}

.btn-danger-link:hover {
  color: var(--error-hover, #c53030);
}

.btn-danger-link:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.email-confirm-input {
  width: 100%;
  padding: 0.6rem;
  border-radius: 7px;
  border: 1px solid var(--form-input-border, #e6e6e6);
  font-size: 1rem;
  background: var(--form-input-bg, #ffffff);
  color: var(--text, #1a1a1a);
  box-sizing: border-box;
  margin-top: 0.5rem;
}

.email-confirm-input:focus {
  outline: none;
  border-color: var(--btn-primary, #4a90e2);
}
</style>
