import { useState } from 'react';
import { Button, Form, Spinner } from 'react-bootstrap';
import { AuthResponse, AuthErrorResponse, User, isAuthErrorResponse } from '@/types/auth';
//import { Helmet, HelmetProvider } from 'react-helmet-async';

import utils from '@/ts/utils.ts';
import ForgotPasswordModal from '@/components/modals/ForgotPasswordModal';

type SpinnerState = Record<string, boolean>;
type FormErrors = Record<string, string>;

function Login() {
    const [isLoading, setIsLoading] = useState(false);
    const [spinners, setSpinnersState] = useState<SpinnerState>({});
    const [formErrors, setFormErrors] = useState<FormErrors>({});
    const [username, setUsername] = useState('');
    const [password, setPassword] = useState('');
    const [showForgotPasswordModal, setShowForgotPasswordModal] = useState(false);
    //const [user, setUser] = useState<User | null>(null);
    const [loginError, setLoginError] = useState<boolean>(false);
    const [loginErrorMessage, setLoginErrorMessage] = useState<string>('');

    //const setSpinners = (newValues: Partial<SpinnerState>) => {
    //    setSpinnersState((prevSpinners) => ({
    //        ...prevSpinners,
    //        ...newValues,
    //    }));
    //};
    const setSpinners = (newValues: Partial<SpinnerState>) => {
        setSpinnersState((prevSpinners) => {
            const updatedSpinners: SpinnerState = { ...prevSpinners };
            for (const key in newValues) {
                if (newValues[key] !== undefined) {
                    updatedSpinners[key] = newValues[key] as boolean;
                }
            }
            return updatedSpinners;
        });
    };

    const handleCloseForgotPasswordModal = () => {
        setShowForgotPasswordModal(false);
    };

    const validateLoginForm = () => {
        setFormErrors({});

        const errors: FormErrors = {};
        if (!username.trim()) {
            errors.username = 'Username is required';
        //} else if (!/\S+@\S+\.\S+/.test(email)) {
        //    errors.email = 'Invalid email address';
        }
        if (!password.trim()) {
            errors.password = 'Password is required';
        }

        if (Object.keys(errors).length > 0) {
            setFormErrors(errors);
        }
    };

    const handleLogin = async (e: React.FormEvent) => {
        e.preventDefault();
        setIsLoading(true);
        spinners.Login = true;
        setSpinners(spinners);

        validateLoginForm();

        if (Object.keys(formErrors).length > 0) return;

        //setUser(null);
        setLoginError(false);
        setLoginErrorMessage('');
        let loggedInUser: User | null = null;
        let hadLoginError: boolean = false;
        let hadLoginErrorMessage: string = '';
        await utils.webMethod<AuthResponse>({
            methodPage: 'authentication',
            methodName: 'authenticate',
            parameters: { username, password },
            success: (json: AuthResponse) => {
                try {
                    loggedInUser = json.user;
                    //setUser(loggedInUser);
                }
                catch {
                    const errorMsg: string = "Unexpected Error";
                    hadLoginError = true;
                    hadLoginErrorMessage = errorMsg;   
                }
            },
            error: (err: unknown) => {
                let errorMsg: string = "Unexpected Error";
                if (isAuthErrorResponse(err)) {
                    if (err && err as AuthErrorResponse) {
                        if (err.data) {
                            if (err.data.message)
                                errorMsg = err.data.message;
                        }
                        console.error(errorMsg);
                        setLoginErrorMessage(errorMsg);
                    }
                }
                hadLoginError = true;
                hadLoginErrorMessage = errorMsg;   
            }
        });

        if (hadLoginError) {
            setLoginErrorMessage(hadLoginErrorMessage);
            setLoginError(true);
            setIsLoading(false);
            spinners.Login = false;
            setSpinners(spinners);
            return;
        }

        if (loggedInUser == null) {
            setLoginError(true);
            setIsLoading(false);
            spinners.Login = false;
            setSpinners(spinners);
        } else {
            await finishUserLogin(loggedInUser);
        }
    };

    const finishUserLogin = async (loggedInUser: User) => {
        setIsLoading(false);
        spinners.Login = false;
        spinners.LoginWithPasskey = false;
        setSpinners(spinners);

        utils.localStorage("session_currentUser", loggedInUser);

        const redirectUrl = utils.sessionStorage("redirect_url");
        if (redirectUrl) {
            utils.sessionStorage("redirect_url", null);
            document.location.href = redirectUrl;
        } else {
            document.location.href = '/home';
        }
    };

    return (
        <div className="container">
            <div className="row text-center mt-5">
                <h1>surge365 - React</h1>
            </div>
            <div className="row text-center" style={{ maxWidth: '400px', margin: 'auto' }}>
                <h3 className="form-signin-heading mt-3 mb-1">Please sign in</h3>
                <Form id="frmLogin" onSubmit={handleLogin}>
                    {loginError && (
                        <Form.Label style={{ color: 'red' }}>{loginErrorMessage ?? "Login error"}</Form.Label>
                    )}
                    <Form.Group className="mb-3" controlId="txtUsernamel">
                        <Form.Label className="visually-hidden">Username</Form.Label>
                        <Form.Control
                            type="username"
                            placeholder="Username"
                            value={username}
                            onChange={(e) => setUsername(e.target.value)}
                            required
                            autoFocus
                            size="sm"
                        />
                        {spinners.Username && <Spinner animation="border" size="sm" />}
                    </Form.Group>

                    <Form.Group className="mb-3" controlId="txtPassword">
                        <Form.Label className="visually-hidden">Password</Form.Label>
                        <Form.Control
                            type="password"
                            placeholder="Password"
                            value={password}
                            onChange={(e) => setPassword(e.target.value)}
                            required
                            size="sm"
                        />
                    </Form.Group>

                    <Button className="bg-orange w-100" type="submit" disabled={isLoading}>
                        {spinners.Login && <Spinner animation="border" size="sm" className="me-2" />}
                        {isLoading && spinners.Login ? 'Signing in...' : 'Sign in'}
                    </Button>
                    <Button variant="secondary" className="w-100 mt-2" onClick={() => setShowForgotPasswordModal(true)}>
                        Forgot Password
                    </Button>
                </Form>
            </div>

            <ForgotPasswordModal show={showForgotPasswordModal} onClose={handleCloseForgotPasswordModal} />
        </div>
    );
}

export default Login;
