/**
 * ChangePasswordPage — forced password change gate (M2-T07).
 *
 * Shown when the authenticated user has force_password_change === true.
 * Blocks access to all other pages until the password is changed.
 *
 * Behaviours:
 * - If the current user does NOT have force_password_change, redirect to '/'
 *   (mirrors LoginPage's already-authenticated guard).
 * - POST /api/auth/password with { current_password, new_password, confirm_password }.
 * - On ApiError 400 → show a generic failure message (do not leak details).
 * - On success → invalidate ['session'] so SessionProvider re-fetches with
 *   force_password_change=false, then navigate to '/' to enter the app.
 */

import { useState } from 'react'
import { useNavigate, useLocation, Navigate } from 'react-router-dom'
import { useQueryClient } from '@tanstack/react-query'
import {
  Container,
  Paper,
  Title,
  Text,
  PasswordInput,
  Button,
  Alert,
  Stack,
  Center,
} from '@mantine/core'
import { useSession } from '../auth/SessionProvider'
import apiClient from '../api/client'
import { ApiError } from '../api/client'

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

interface LocationState {
  from?: { pathname: string }
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

export function ChangePasswordPage() {
  const { user } = useSession()
  const navigate = useNavigate()
  const location = useLocation()
  const queryClient = useQueryClient()

  const [currentPassword, setCurrentPassword] = useState('')
  const [newPassword, setNewPassword] = useState('')
  const [confirmPassword, setConfirmPassword] = useState('')
  const [error, setError] = useState<string | null>(null)
  const [loading, setLoading] = useState(false)

  // Guard: if the user is authenticated but NOT in forced-change state, redirect
  // to the app. This prevents a non-forced user from sitting on /change-password.
  // (Mirrors LoginPage's already-authenticated redirect.)
  if (user && !user.force_password_change) {
    const from = (location.state as LocationState)?.from?.pathname ?? '/'
    return <Navigate to={from} replace />
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    setError(null)

    // Client-side validation: confirm passwords match before hitting the server.
    if (newPassword !== confirmPassword) {
      setError('New passwords do not match.')
      return
    }

    setLoading(true)

    try {
      await apiClient.POST('/api/auth/password', {
        body: {
          current_password: currentPassword,
          new_password: newPassword,
          confirm_password: confirmPassword,
        },
      })

      // Success: refresh session so force_password_change becomes false,
      // then navigate into the app — the guard above (and ProtectedRoute) will
      // no longer block access once the session is updated.
      await queryClient.invalidateQueries({ queryKey: ['session'] })
      navigate('/', { replace: true })
    } catch (err) {
      if (err instanceof ApiError && err.status === 400) {
        // Generic failure message — do not leak backend detail.
        setError('Password change failed. Please check your current password and try again.')
      } else {
        setError('An unexpected error occurred. Please try again.')
      }
    } finally {
      setLoading(false)
    }
  }

  return (
    <Center mih="100vh">
      <Container size="xs" w="100%">
        <Paper shadow="sm" p="xl" radius="md" withBorder>
          <Title order={2} mb="xs" ta="center">
            Change Password
          </Title>
          <Text c="dimmed" size="sm" mb="lg" ta="center">
            You must change your password before continuing.
          </Text>

          {error && (
            <Alert color="red" mb="md" role="alert" data-testid="change-password-error">
              {error}
            </Alert>
          )}

          <form onSubmit={handleSubmit} data-testid="change-password-form">
            <Stack gap="md">
              <PasswordInput
                label="Current Password"
                placeholder="Enter your current password"
                value={currentPassword}
                onChange={(e) => setCurrentPassword(e.currentTarget.value)}
                required
                autoComplete="current-password"
                data-testid="current-password-input"
              />

              <PasswordInput
                label="New Password"
                placeholder="Enter your new password"
                value={newPassword}
                onChange={(e) => setNewPassword(e.currentTarget.value)}
                required
                autoComplete="new-password"
                data-testid="new-password-input"
              />

              <PasswordInput
                label="Confirm New Password"
                placeholder="Confirm your new password"
                value={confirmPassword}
                onChange={(e) => setConfirmPassword(e.currentTarget.value)}
                required
                autoComplete="new-password"
                data-testid="confirm-password-input"
              />

              <Button
                type="submit"
                fullWidth
                loading={loading}
                mt="sm"
                data-testid="change-password-submit"
              >
                Change Password
              </Button>
            </Stack>
          </form>
        </Paper>
      </Container>
    </Center>
  )
}
