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

import CheckCircleIcon from '@mui/icons-material/CheckCircle';
import { Box, Button, FormControlLabel, FormHelperText, TextField, Typography } from '@mui/material';

import Api from '@northern.tech/store/api/general-api';
import zxcvbn from 'zxcvbn';

import { PasswordField } from '../components/PasswordField';
import { MIN_PASSWORD_LENGTH, PASSWORD_COMPLEXITY } from '../constants';
import { useNotify } from '../notify';
import { useCompleteStyles } from '../styles';

interface FormData {
  username?: string;
  password?: string;
  email?: string;
  confirmPassword?: string;
  remember: boolean;
}

interface FormErrors {
  password: string;
  email: string;
  username: string;
}

interface CompleteResponse {
  success: boolean;
  error?: string;
}

export const Complete = () => {
  const { classes } = useCompleteStyles();
  const navigate = useNavigate();
  const { error: notifyError, success: notifySuccess } = useNotify();

  const [formData, setFormData] = useState<FormData>({
    username: '',
    password: '',
    email: '',
    confirmPassword: '',
    remember: false
  });
  const [error, setError] = useState<string | null>(null);
  const [showPassword, setShowPassword] = useState(false);
  const [showConfirmPassword, setShowConfirmPassword] = useState(false);

  const validation = useMemo<FormErrors>(() => {
    const errors: FormErrors = { password: '', username: '', email: '' };

    if (formData.username && !/^[a-zA-Z0-9]+$/.test(formData.username)) {
      errors.username = 'Username must be alphanumeric';
    }

    if (formData.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
      errors.email = 'Wrong email format';
    }

    if (formData.password) {
      if (formData.password.length < MIN_PASSWORD_LENGTH) {
        errors.password = 'Password must be at least 8 characters';
      } else {
        const {
          feedback: { suggestions = [] },
          score = 0
        } = zxcvbn(formData.password);
        if (score < PASSWORD_COMPLEXITY) {
          errors.password = suggestions[0] || 'Password is not strong enough';
        }
      }
    }

    if (formData.password !== formData.confirmPassword && formData.confirmPassword) {
      errors.password = 'Passwords do not match';
    }

    return errors;
  }, [formData]);

  const isValid = useMemo(() => {
    const hasErrors = validation.password || validation.username || validation.email;
    const hasValues = formData.username && formData.password && formData.confirmPassword && formData.email;
    return !hasErrors && hasValues;
  }, [validation, formData]);

  const handleChange = (field: keyof FormData) => (e: React.ChangeEvent<HTMLInputElement | { value: string; name?: string }>) => {
    const value = field === 'remember' ? (e.target as HTMLInputElement).checked : e.target.value;
    setFormData(prev => ({ ...prev, [field]: value }));
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!isValid) return;

    try {
      const response = await Api.post<CompleteResponse>('/setup/complete_setup', formData);
      const { success = false, error = '' } = response.data;

      if (!success) {
        setError(error);
        if (error.includes('Invalid session')) {
          setTimeout(() => navigate('/'), 1500);
        }
      } else {
        notifySuccess('User successfully created. Redirecting...');
        setTimeout(() => (window.location.href = '/'), 2000);
      }
    } catch (err: any) {
      notifyError(err.data || 'An error occurred');
    }
  };

  return (
    <Box className={classes.container}>
      <Box id="login" className={`setup complete ${classes.loginBox}`}>
        <Box sx={{ width: 460 }} className="login-box">
          <Box>
            <Box sx={{ textAlign: 'center' }}>
              <Typography variant="h4" component="h2" sx={{ justifyContent: 'center' }} className="flex flex--align_center">
                <CheckCircleIcon className={classes.titleIcon} />
                Success!
              </Typography>
              <Typography className={`${classes.subtitle} margin-bottom margin-top-small`}>Complete setup by creating your first admin user.</Typography>
            </Box>
            <Box component="form" onSubmit={handleSubmit} className="form-horizontal" id="setup-code">
              <Box className="control-group">
                <Typography component="label" className="control-label" htmlFor="username">
                  Username
                </Typography>
                <Box className="controls">
                  <Box className="input-append">
                    <TextField
                      id="username"
                      name="username"
                      autoComplete="off"
                      className="input-xlarge"
                      value={formData.username}
                      onChange={handleChange('username')}
                      error={!!validation.username}
                      fullWidth
                    />
                  </Box>
                  <FormHelperText error>{validation.username}</FormHelperText>
                </Box>
              </Box>

              <Box className="control-group">
                <Typography component="label" className="control-label" htmlFor="email">
                  Email
                </Typography>
                <Box className="controls">
                  <Box className="input-append">
                    <TextField
                      id="email"
                      name="email"
                      className="input-xlarge"
                      value={formData.email}
                      onChange={handleChange('email')}
                      error={!!validation.email}
                      fullWidth
                    />
                  </Box>
                  <FormHelperText error>{validation.email}</FormHelperText>
                </Box>
              </Box>

              <Box className="control-group">
                <Typography component="label" className="control-label" htmlFor="password">
                  Password
                </Typography>
                <Box className="controls">
                  <Box>
                    <PasswordField
                      id="password"
                      label=""
                      value={formData.password}
                      onChange={value => handleChange('password')({ target: { value } })}
                      error={validation.password}
                      showPassword={showPassword}
                      onToggleVisibility={() => setShowPassword(!showPassword)}
                    />
                  </Box>
                </Box>
              </Box>

              <Box className="control-group">
                <Typography component="label" className="control-label" htmlFor="confirmPassword">
                  Confirm password
                </Typography>
                <Box className="controls">
                  <Box>
                    <PasswordField
                      id="confirmPassword"
                      label=""
                      value={formData.confirmPassword}
                      onChange={value => handleChange('confirmPassword')({ target: { value } })}
                      error={validation.password}
                      showPassword={showConfirmPassword}
                      onToggleVisibility={() => setShowConfirmPassword(!showConfirmPassword)}
                    />
                  </Box>
                  <FormHelperText error>{validation.password}</FormHelperText>
                </Box>
              </Box>
              {error && <Box className={`alert alert-error`}>{error}</Box>}
              <Box className="control-group margin-top-small actions">
                <Box sx={{ marginRight: 60 }} className="controls flex flex-space-between flex--align_center">
                  <FormControlLabel
                    control={<input type="checkbox" checked={formData.remember} onChange={handleChange('remember')} name="remember" value="1" />}
                    label="Remember me"
                    title="Stay logged in for one week."
                    className={classes.rememberMeLabel}
                  />
                  <Button type="submit" className="btn btn-primary pull-right" variant="contained" disabled={!isValid}>
                    Create user
                  </Button>
                </Box>
              </Box>
            </Box>
          </Box>
        </Box>
      </Box>
    </Box>
  );
};

export default Complete;
