import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useDispatch } from 'react-redux';

// material-ui
import {
  Button,
  Grid,
  InputLabel,
  Stack,
  TextField,
  IconButton,
  InputAdornment,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
  Typography,
  Box
} from '@mui/material';

// third party
import * as Yup from 'yup';
import { Formik } from 'formik';

// project imports
import AnimateButton from 'components/@extended/AnimateButton';
import { handleLogin } from 'auth/index';
import axios from 'axios';
import { apiPath } from '../../../auth/utils';
import { LOGIN_PATH } from '../../../utils/ApiPathConst';
import { LIONER_LOGIN_THEME } from '../../../themes/themeConst';
import { ThemeProvider } from '@emotion/react';

// assets
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
import { QRCodeSVG } from 'qrcode.react';

// ============================|| AUTH LOGIN WITH 2FA ||============================ //

const AuthLogin = () => {
  const dispatch = useDispatch();
  const navigate = useNavigate();

  const [showPassword, setShowPassword] = useState(false);
  const [userName, setUserName] = useState('');
  const [userPassword, setUserPassword] = useState('');
  const [errors, setErrors] = useState({});

  // 2FA States
  const [twoFAModalOpen, setTwoFAModalOpen] = useState(false);
  const [twoFAMode, setTwoFAMode] = useState('login');
  const [qrUrl, setQrUrl] = useState('');
  const [twoFACode, setTwoFACode] = useState('');
  const [twoFAError, setTwoFAError] = useState('');

  const handleClickShowPassword = () => setShowPassword(!showPassword);
  const handleMouseDownPassword = (event) => event.preventDefault();

  const onUserNameChange = (e) => setUserName(e.target.value);
  const onPasswordChange = (e) => setUserPassword(e.target.value);

  // === CENTRALIZED LOGIN & REDIRECT FUNCTION ===
  const performLoginAndRedirect = async (loginPayload, is2FA = false) => {
    await dispatch(handleLogin(loginPayload));

    // Determine target path using abilities from payload
    const abilities = loginPayload.abilities || [];
    let targetPath = '/client';

    const hasMaintainClient = abilities.some(a => a.startsWith('MAINTAIN') && a.includes('CLIENT'));
    const hasViewUser = abilities.some(a => a.startsWith('VIEW') && a.includes('USER'));

    if (!is2FA && loginPayload.twoFactorEnabled === false) {
      targetPath = '/profile';
    } else if (hasMaintainClient) {
      targetPath = '/client';
    } else if (hasViewUser) {
      targetPath = '/userSearchview';
    }

    const lastPath = localStorage.getItem('lastVisitedPath');
    if (lastPath && targetPath === '/client') {
      targetPath = lastPath;
    }
    localStorage.removeItem('lastVisitedPath');

    // Full page redirect to force AbilityProvider to rebuild
    window.location.href = targetPath;
  };

  const tryLogin = () => {
    const formErrors = {};
    if (!userName) formErrors.loginError = 'Username is required.';
    if (!userPassword) formErrors.passwordError = 'Password is required.';
    setErrors(formErrors);

    if (Object.keys(formErrors).length === 0) {
      axios
        .post(`${apiPath}${LOGIN_PATH}`, { username: userName, password: userPassword })
        .then(async (response) => {
          const data = response.data;

          if (data.requires2FA) {
            setTwoFAMode('login');
            setTwoFAModalOpen(true);
            return;
          }

          if (data.accessToken) {
            const loginPayload = {
              id: data.id,
              fullName: data.name,
              email: data.email,
              role: data.role,
              abilities: data.abilities || [],
              subDivisionId: data.subDivisionId,
              lotusNotesUser: data.lotusNotesUser,
              accessToken: data.accessToken,
              refreshToken: data.refreshToken,
              twoFactorEnabled: data.twoFactorEnabled ?? false
            };

            await performLoginAndRedirect(loginPayload);
          }
        })
        .catch((error) => {
          setErrors({ passwordError: error.response?.data?.message || 'Invalid credentials' });
        });
    }
  };

  const handle2FASubmit = () => {
    if (twoFACode.length !== 6 || !/^\d+$/.test(twoFACode)) {
      setTwoFAError('Please enter a valid 6-digit code');
      return;
    }

    const endpoint = twoFAMode === 'setup' ? '/2fa/verify-setup' : '/2fa/verify-login';
    const payload = { code: twoFACode, username: userName };

    axios
      .post(`${apiPath}${endpoint}`, payload)
      .then(async (res) => {
        const data = res.data;

        if (twoFAMode === 'setup') {
          alert('2FA enabled!');
          setTwoFAModalOpen(false);
          return;
        }

        const loginPayload = {
          id: data.id,
          fullName: data.name,
          email: data.email,
          role: data.role,
          abilities: data.abilities || [],
          subDivisionId: data.subDivisionId || null,
          lotusNotesUser: data.lotusNotesUser || null,
          accessToken: data.accessToken,
          refreshToken: data.refreshToken,
          twoFactorEnabled: true
        };

        await performLoginAndRedirect(loginPayload, true);

        setTwoFAModalOpen(false);
        setTwoFACode('');
        setTwoFAError('');
      })
      .catch((err) => {
        console.error('2FA verification failed:', err);
        setTwoFAError(err.response?.data?.message || 'Invalid or expired code');
      });
  };

  return (
    <>
      <Formik
        initialValues={{ userName: '', password: '', submit: null }}
        validationSchema={Yup.object().shape({
          userName: Yup.string().required('Username is required'),
          password: Yup.string().required('Password is required')
        })}
      >
        {({ handleBlur }) => (
          <form>
            <ThemeProvider theme={LIONER_LOGIN_THEME}>
              <Grid container spacing={3}>
                <Grid item xs={12}>
                  <Stack spacing={1}>
                    <InputLabel htmlFor="username">User Name</InputLabel>
                    <TextField
                      id="username"
                      value={userName}
                      onBlur={handleBlur}
                      onChange={onUserNameChange}
                      placeholder="Enter user name"
                      fullWidth
                      variant="outlined"
                      error={!!errors.loginError}
                      helperText={errors.loginError}
                    />
                  </Stack>
                </Grid>

                <Grid item xs={12}>
                  <Stack spacing={1}>
                    <InputLabel htmlFor="password-login">Password</InputLabel>
                    <TextField
                      fullWidth
                      variant="outlined"
                      error={!!errors.passwordError}
                      helperText={errors.passwordError}
                      id="password-login"
                      type={showPassword ? 'text' : 'password'}
                      value={userPassword}
                      onBlur={handleBlur}
                      onChange={onPasswordChange}
                      InputProps={{
                        endAdornment: (
                          <InputAdornment position="end">
                            <IconButton
                              onClick={handleClickShowPassword}
                              onMouseDown={handleMouseDownPassword}
                              edge="end"
                              size="large"
                            >
                              {showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
                            </IconButton>
                          </InputAdornment>
                        )
                      }}
                      placeholder="Enter password"
                    />
                  </Stack>
                </Grid>

                <Grid item xs={12}>
                  <AnimateButton>
                    <Button
                      onClick={tryLogin}
                      sx={{ height: '50px' }}
                      fullWidth
                      size="large"
                      variant="contained"
                      color="primary"
                    >
                      Login
                    </Button>
                  </AnimateButton>
                </Grid>
              </Grid>
            </ThemeProvider>
          </form>
        )}
      </Formik>

      <Dialog open={twoFAModalOpen} onClose={() => setTwoFAModalOpen(false)} maxWidth="sm" fullWidth>
        <DialogTitle>
          {twoFAMode === 'setup' ? 'Set Up Two-Factor Authentication' : 'Two-Factor Authentication Required'}
        </DialogTitle>
        <DialogContent>
          {twoFAMode === 'setup' && qrUrl && (
            <Box sx={{ textAlign: 'center', my: 3 }}>
              <Typography variant="body1" gutterBottom>
                Scan this QR code with <strong>Microsoft Authenticator</strong>:
              </Typography>
              <QRCodeSVG value={qrUrl} size={220} level="M" />
              <Typography variant="caption" display="block" sx={{ mt: 2 }}>
                After scanning, enter a code from the app to verify.
              </Typography>
            </Box>
          )}

          {twoFAMode === 'login' && (
            <Typography variant="body1" sx={{ mb: 2 }}>
              Open Microsoft Authenticator and enter the 6-digit code for your account.
            </Typography>
          )}

          <TextField
            autoFocus
            fullWidth
            label="6-Digit Code"
            value={twoFACode}
            onChange={(e) => setTwoFACode(e.target.value.replace(/\D/g, '').slice(0, 6))}
            onKeyDown={(e) => {
              if (e.key === 'Enter' && twoFACode.length === 6) handle2FASubmit();
            }}
            error={!!twoFAError}
            helperText={twoFAError}
            inputProps={{ maxLength: 6 }}
            sx={{ mt: 2 }}
          />
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setTwoFAModalOpen(false)}>Cancel</Button>
          <Button onClick={handle2FASubmit} variant="contained" disabled={twoFACode.length !== 6}>
            Verify
          </Button>
        </DialogActions>
      </Dialog>
    </>
  );
};

export default AuthLogin;