<template>
  <div class="view">
    <h2>Profile</h2>

    <div v-if="loading" class="loading-message">Loading profile...</div>
    <div v-else class="profile-card">
      <div v-if="errorMsg" class="error-banner" aria-live="polite">{{ errorMsg }}</div>

      <ProfileSection title="User" :defaultOpen="true">
        <div class="name-fields" @focusout="handleNameFocusOut">
          <div class="field-group">
            <label for="first-name">First Name</label>
            <input
              id="first-name"
              v-model="firstName"
              type="text"
              maxlength="64"
              :disabled="saving"
            />
          </div>
          <div class="field-group">
            <label for="last-name">Last Name</label>
            <input
              id="last-name"
              v-model="lastName"
              type="text"
              maxlength="64"
              :disabled="saving"
            />
          </div>
        </div>
        <div class="field-group">
          <label>Image</label>
          <ImagePicker
            :modelValue="imageId"
            @update:modelValue="onImageChange"
            @add-image="onAddImage"
            :image-type="1"
          />
        </div>
      </ProfileSection>

      <ProfileSection title="Account">
        <div class="field-group">
          <label for="email">Email Address</label>
          <input id="email" type="email" :value="email" disabled class="readonly-input" />
        </div>
        <div class="action-links">
          <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>
      </ProfileSection>

      <ProfileSection title="Notifications">
        <div class="toggle-stack">
          <ToggleField
            label="Daily Digest"
            :modelValue="emailDigestEnabled"
            @update:modelValue="onToggleDigest"
            :disabled="saving"
            description="Receive a 9pm summary of pending chore and reward requests with one-click approve/deny links."
          />
          <ToggleField
            label="Push Notifications"
            :modelValue="pushEnabled"
            @update:modelValue="onTogglePush"
            :disabled="saving || pushPermissionDenied"
            description="Receive instant push notifications when a chore or reward needs your approval."
            :error="pushError"
          />
        </div>
      </ProfileSection>

      <ProfileSection title="Help">
        <ToggleField
          label="Show tutorial tips"
          :modelValue="tutorialEnabled"
          @update:modelValue="onToggleTutorial"
          description="Show helpful tips as I use the app."
        />
        <button type="button" class="btn-link btn-link-space" @click="openRestartConfirm">
          Restart tutorial
        </button>
      </ProfileSection>
    </div>

    <!-- Password reset modal -->
    <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>

    <!-- Restart confirmation -->
    <ModalDialog
      v-if="showRestartConfirm"
      title="Tutorial Restart"
      @close="showRestartConfirm = false"
    >
      <div class="modal-message">
        Start the tour again from the beginning? You'll see the tips again as you use the app.
      </div>
      <div class="modal-actions">
        <button class="btn btn-secondary" @click="showRestartConfirm = false">Cancel</button>
        <button class="btn btn-primary" @click="confirmRestartTutorial">Restart</button>
      </div>
    </ModalDialog>

    <!-- Restart success -->
    <ModalDialog
      v-if="showRestartSuccess"
      title="Tutorial Restart"
      @close="showRestartSuccess = false"
    >
      <div class="modal-message">Tutorial mode has been restarted.</div>
      <div class="modal-actions">
        <button class="btn btn-primary" @click="showRestartSuccess = false">OK</button>
      </div>
    </ModalDialog>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import ProfileSection from './ProfileSection.vue'
import ImagePicker from '@/components/utils/ImagePicker.vue'
import ToggleField from '@/components/shared/ToggleField.vue'
import ModalDialog from '@/components/shared/ModalDialog.vue'
import {
  isSubscribedToPush,
  subscribeToPushWithResult,
  unsubscribeFromPush,
  getPushPermissionState,
  setPushOptOut,
} from '@/services/pushSubscription'
import { parseErrorResponse, isEmailValid } from '@/common/api'
import { ALREADY_MARKED } from '@/common/errorCodes'
import { logoutUser, suppressForceLogout } from '@/stores/auth'
import { tutorialEnabled, setTutorialEnabled, resetAllProgress } from '@/tutorial/controller'
import '@/assets/styles.css'

const router = useRouter()

// Profile data
const loading = ref(true)
const saving = ref(false)
const errorMsg = ref('')

const firstName = ref('')
const lastName = ref('')
const imageId = ref<string | null>(null)
const email = ref('')
const emailDigestEnabled = ref(true)
const pushEnabled = ref(false)
const pushPermissionDenied = ref(false)
const pushError = ref('')

const localImageFile = ref<File | null>(null)

// Modal state
const resetting = ref(false)
const showModal = ref(false)
const modalTitle = ref('')
const modalSubtitle = ref('')
const modalMessage = ref('')

const showDeleteWarning = ref(false)
const confirmEmail = ref('')
const deletingAccount = ref(false)
const showDeleteSuccess = ref(false)
const showDeleteError = ref(false)
const deleteErrorMessage = ref('')

const showRestartConfirm = ref(false)
const showRestartSuccess = ref(false)

// Load profile
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()
    pushPermissionDenied.value = getPushPermissionState() === 'denied'
    const pushSubscribed = await isSubscribedToPush()
    firstName.value = data.first_name || ''
    lastName.value = data.last_name || ''
    imageId.value = data.image_id || null
    email.value = data.email || ''
    emailDigestEnabled.value = data.email_digest_enabled !== false
    pushEnabled.value = data.push_notifications_enabled !== false && pushSubscribed
  } catch {
    errorMsg.value = 'Could not load user profile.'
  } finally {
    loading.value = false
  }
})

function handleNameFocusOut(event: FocusEvent) {
  const wrapper = event.currentTarget as HTMLElement
  const relatedTarget = event.relatedTarget as HTMLElement | null
  if (relatedTarget && wrapper.contains(relatedTarget)) {
    return
  }
  saveNames()
}

// ─── Auto-save: names ───
async function saveNames() {
  if (saving.value) return
  saving.value = true
  errorMsg.value = ''
  try {
    const res = await fetch('/api/user/profile', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        first_name: firstName.value,
        last_name: lastName.value,
      }),
    })
    if (!res.ok) throw new Error('Failed to update profile')
  } catch {
    errorMsg.value = 'Failed to update profile.'
  } finally {
    saving.value = false
  }
}

// ─── Auto-save: image ───
function onImageChange(id: string | null) {
  if (id === 'local-upload') {
    // localImageFile is set by onAddImage which fires first
    uploadLocalImage()
  } else {
    localImageFile.value = null
    imageId.value = id
    saveImage(id)
  }
}

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

async function uploadLocalImage() {
  if (!localImageFile.value) return
  saving.value = true
  errorMsg.value = ''
  try {
    const formData = new FormData()
    formData.append('file', localImageFile.value)
    formData.append('type', '1')
    formData.append('permanent', 'true')
    const resp = await fetch('/api/image/upload', {
      method: 'POST',
      body: formData,
    })
    if (!resp.ok) throw new Error('Image upload failed')
    const data = await resp.json()
    imageId.value = data.id
    await saveImage(data.id)
  } catch {
    errorMsg.value = 'Failed to upload image.'
  } finally {
    saving.value = false
  }
}

async function saveImage(id: string | null) {
  saving.value = true
  errorMsg.value = ''
  try {
    const res = await fetch('/api/user/profile', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ image_id: id }),
    })
    if (!res.ok) throw new Error('Failed to update profile')
  } catch {
    errorMsg.value = 'Failed to update profile.'
  } finally {
    saving.value = false
  }
}

// ─── Auto-save: toggles ───
async function onToggleDigest(val: boolean) {
  emailDigestEnabled.value = val
  if (saving.value) return
  saving.value = true
  errorMsg.value = ''
  try {
    const res = await fetch('/api/user/profile', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email_digest_enabled: val }),
    })
    if (!res.ok) throw new Error('Failed to update profile')
  } catch {
    errorMsg.value = 'Failed to update profile.'
    emailDigestEnabled.value = !val
  } finally {
    saving.value = false
  }
}

async function onTogglePush(val: boolean) {
  const prevPush = pushEnabled.value
  pushEnabled.value = val
  if (saving.value) return
  saving.value = true
  errorMsg.value = ''
  pushError.value = ''
  try {
    const res = await fetch('/api/user/profile', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ push_notifications_enabled: val }),
    })
    if (!res.ok) throw new Error('Failed to update profile')
    const pushOk = await applyPushChange(val)
    if (!pushOk) {
      pushEnabled.value = prevPush
    }
  } catch {
    errorMsg.value = 'Failed to update profile.'
    pushEnabled.value = prevPush
  } finally {
    saving.value = false
  }
}

async function applyPushChange(newValue: boolean): Promise<boolean> {
  pushError.value = ''
  try {
    if (newValue) {
      const result = await subscribeToPushWithResult()
      if (result.ok) {
        setPushOptOut(false)
        return true
      }
      pushError.value =
        result.reason === 'permission_denied'
          ? 'Notifications are blocked. Enable them in your browser settings.'
          : 'Failed to enable push notifications.'
      return false
    } else {
      await unsubscribeFromPush()
      setPushOptOut(true)
      return true
    }
  } catch {
    pushError.value = 'Failed to update push notification settings.'
    return false
  }
}

// ─── Tutorial toggle ───
async function onToggleTutorial(val: boolean) {
  await setTutorialEnabled(val)
}

// ─── Password reset ───
async function resetPassword() {
  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: email.value }),
    })
    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
  }
}

async function handlePasswordModalClose() {
  showModal.value = false
}

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

// ─── Delete account ───
function openDeleteWarning() {
  confirmEmail.value = ''
  showDeleteWarning.value = true
}

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

async function confirmDeleteAccount() {
  if (!isEmailValid(confirmEmail.value)) return
  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
    }
    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
  fetch('/api/auth/logout', {
    method: 'POST',
    credentials: 'include',
  }).finally(() => {
    logoutUser()
    router.push('/')
  })
}

function closeDeleteError() {
  showDeleteError.value = false
  deleteErrorMessage.value = ''
}

// ─── Tutorial restart ───
function openRestartConfirm() {
  showRestartConfirm.value = true
}

async function confirmRestartTutorial() {
  showRestartConfirm.value = false
  await resetAllProgress()
  showRestartSuccess.value = true
}
</script>

<style scoped>
.view {
  max-width: 420px;
  margin: 0 auto;
}

h2 {
  text-align: center;
  margin-bottom: 1.5rem;
  color: #fff;
}

.profile-card {
  background: var(--form-bg);
  border-radius: 12px;
  box-shadow: 0 4px 24px var(--form-shadow);
  padding: 0.5rem 1.5rem 1rem;
}

.loading-message {
  text-align: center;
  color: var(--loading-color, #888);
  font-size: 1rem;
  padding: 2rem 0;
}

.error-banner {
  color: var(--error, #e53e3e);
  font-size: 0.95rem;
  padding: 0.6rem 0;
  margin-bottom: 0.5rem;
  text-align: center;
}

.field-group {
  margin-bottom: 1rem;
}

.field-group label {
  display: block;
  font-weight: 600;
  color: var(--form-label, #444);
  margin-bottom: 0.4rem;
  font-size: 0.95rem;
}

.field-group input[type='text'],
.field-group input[type='email'] {
  width: 100%;
  padding: 0.6rem;
  border-radius: 7px;
  border: 1px solid var(--form-input-border, #e6e6e6);
  font-size: 1rem;
  background: var(--form-input-bg, #fff);
  color: var(--text-primary, #222);
  box-sizing: border-box;
  transition: opacity 0.2s;
}

.field-group input:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.readonly-input {
  background: var(--form-input-bg, #f5f5f5) !important;
  color: var(--form-label, #888) !important;
}

.action-links {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  align-items: flex-start;
}

.toggle-stack {
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
}

.btn-link {
  background: none;
  border: none;
  color: var(--btn-primary, #667eea);
  font-size: 0.95rem;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
}

.btn-link:hover {
  color: var(--btn-primary-hover, #5a67d8);
}

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

.modal-message {
  text-align: center;
  color: var(--dialog-message, #444);
  font-size: 1rem;
  line-height: 1.5;
}

.modal-actions {
  display: flex;
  gap: 1rem;
  justify-content: center;
  margin-top: 1.2rem;
}

.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);
}

@media (max-width: 480px) {
  .profile-card {
    padding: 0.5rem 1rem 1rem;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
  }

  .view {
    max-width: 100%;
    padding: 0 0.5rem;
  }
}
</style>
