'use client';

import Link from 'next/link';
import { usePathname } from 'next/navigation';
import './topbar.css';
import {
  Anchor,
  Avatar,
  Button,
  Card,
  Checkbox,
  Container,
  Grid,
  Group,
  Menu,
  Modal,
  Paper,
  PasswordInput,
  Text,
  TextInput,
  Title,
  UnstyledButton
} from '@mantine/core';
import Cookies from 'js-cookie';
import { useEffect, useState } from 'react';
import { useForm } from '@mantine/form';
import { login, register, logout, me, refreshLoggedIn } from '@/api/auth';
import { User } from '@/api/auth.types';
import { useToggle } from '@mantine/hooks';
import { notifications } from '@mantine/notifications';

interface HeaderItem {
  name: string;
  link: string;
  role?: string;
}

const headerItems: HeaderItem[] = [
  {
    name: 'Races',
    link: '/races'
  },
  {
    name: 'Classes',
    link: '/classes'
  },
  {
    name: 'Feats',
    link: '/feats'
  },
  {
    name: 'Options & Features',
    link: '/options'
  },
  {
    name: 'Backgrounds',
    link: '/backgrounds'
  },
  {
    name: 'Items',
    link: '/items'
  },
  {
    name: 'Spells',
    link: '/spells'
  },
  {
    name: 'Management',
    link: '/management',
    role: 'admin'
  }
];

export default function Topbar() {
  const pathName = usePathname();
  const [modalType, toggle] = useToggle([undefined, 'login', 'register', 'reset']);
  const [headers, setHeaders] = useState<HeaderItem[]>([]);
  const [user, setUser] = useState<User | undefined>(undefined);
  const [refreshId, setRefreshId] = useState<NodeJS.Timeout | undefined>(undefined);

  useEffect(() => {
    if (Cookies.get('logged_in')) {
      me().then((response) => {
        if (response) {
          setRefreshId(refreshLoggedIn());
          setUser(response.user);
        }
      });
    }
  }, []);

  useEffect(() => {
    const h: HeaderItem[] = [];
    headerItems.forEach((item) => {
      if (item.role == undefined || user?.role == item.role) {
        h.push(item);
      }
      setHeaders(h);
    });
  }, [user]);

  return (
    <>
      <nav className='navbar'>
        <div className='left'>
          <Link href={'/'} className='title'>
            Siren
          </Link>
          <div className='header-items'>
            {headers.map((item) => (
              <Link className={`header-item ${pathName == item.link && 'active'}`} href={item.link} key={item.name}>
                {item.name}
              </Link>
            ))}
          </div>
        </div>
        <div className='user-section'>
          {user ? (
            <Menu shadow='md' width={200} openDelay={100} closeDelay={400}>
              <Menu.Target>
                <UnstyledButton className='user user-button'>
                  <Group>
                    <Avatar />
                    <div style={{ flex: 1 }}>
                      <Text size='sm' fw={500}>
                        {user.first_name} {user.last_name}
                      </Text>

                      <Text c='dimmed' size='xs'>
                        {user.role}
                      </Text>
                    </div>
                  </Group>
                </UnstyledButton>
              </Menu.Target>
              <Menu.Dropdown>
                <Card>
                  <Card.Section h={140} style={{}} />
                  <Avatar size={80} radius={80} mx={'auto'} mt={-30} />
                  <Text ta='center' fz='lg' fw={500} mt='sm'>
                    {user.first_name} {user.last_name}
                  </Text>
                  <Text ta='center' fz='sm' c='dimmed'>
                    {user.role}
                  </Text>
                  <Grid mt='xl'>
                    <Grid.Col span={6}>
                      <Button
                        fullWidth
                        radius='md'
                        size='xs'
                        variant='default'
                        onClick={() => {
                          toggle(undefined);
                        }}
                      >
                        Profile
                      </Button>
                    </Grid.Col>
                    <Grid.Col span={6}>
                      <Button
                        fullWidth
                        radius='md'
                        size='xs'
                        variant='default'
                        onClick={async () => {
                          const response = await logout();
                          if (response?.status == 200) {
                            Cookies.remove('logged_in');
                            if (refreshId) {
                              clearInterval(refreshId);
                            }
                            setUser(undefined);
                          }
                        }}
                      >
                        Logout
                      </Button>
                    </Grid.Col>
                  </Grid>
                </Card>
              </Menu.Dropdown>
            </Menu>
          ) : (
            <Group className='user'>
              <Button onClick={() => toggle('login')}>Login</Button>
              <Button variant='outline' onClick={() => toggle('register')}>
                Sign up
              </Button>
            </Group>
          )}
        </div>
      </nav>
      <LoginModal type={modalType} toggle={toggle} setUser={setUser} setRefreshId={setRefreshId} />
    </>
  );
}

interface LoginModalProps {
  type?: string;
  toggle: any;
  setUser: (user: User) => void;
  setRefreshId: (id: NodeJS.Timeout) => void;
}

function LoginModal({ type, toggle, setUser, setRefreshId }: LoginModalProps) {
  function passwordValidator(value: string) {
    if (value.trim().length < 10) {
      return 'Password must be at least 10 characters';
    }
    if (value.trim().length >= 128) {
      return 'Password must be at most 128 characters';
    }
    if (!/(\d)/.test(value)) {
      return 'Password must contain at least one number';
    }
    if (!/[a-z]/.test(value)) {
      return 'Password must contain at least one lowercase letter';
    }
    if (!/[A-Z]/.test(value)) {
      return 'Password must contain at least one uppercase letter';
    }
    if (!/[!@#$%^&*]/.test(value)) {
      return 'Password must contain at least one special character';
    }
    return null;
  }

  function emailValidator(value: string) {
    if (value.trim().length == 0) {
      return 'Email is required';
    }
    if (!/^\S+@\S+$/.test(value)) {
      return 'Invalid email';
    }
    return null;
  }

  const registerForm = useForm({
    initialValues: {
      firstName: '',
      lastName: '',
      email: '',
      password: ''
    },
    validate: {
      firstName: (value) => (value.trim().length > 0 ? null : 'First name is required'),
      lastName: (value) => (value.trim().length > 0 ? null : 'Last name is required'),
      email: emailValidator,
      password: passwordValidator
    }
  });

  const loginForm = useForm({
    initialValues: {
      email: '',
      password: '',
      remember: false
    }
  });

  const resetForm = useForm({
    initialValues: {
      email: ''
    }
  });

  function onClose() {
    toggle(undefined);
    registerForm.reset();
    resetForm.reset();
    if (!loginForm.values.remember) {
      loginForm.reset();
    }
  }

  return (
    <Modal opened={type !== undefined} onClose={onClose} withCloseButton={false}>
      {type == 'reset' ? (
        <Container>
          <Title ta='center'>Reset password</Title>
          <Text c='dimmed' size='sm' ta='center' mt={5}>
            Enter your email and we will send you a link to reset your password.{' '}
            <Anchor size='sm' component='a' onClick={() => toggle('login')}>
              Go Back
            </Anchor>
          </Text>
          <Paper withBorder shadow='md' p={30} mt={30} radius='md'>
            <form onSubmit={resetForm.onSubmit(async (values) => console.log(values))}>
              <TextInput label='Email' placeholder='you@example.com' required {...resetForm.getInputProps('email')} />
              <Button type='submit' fullWidth mt='xl'>
                Reset password
              </Button>
            </form>
          </Paper>
        </Container>
      ) : type == 'register' ? (
        <Container>
          <Title ta='center'>Create account</Title>
          <Text c='dimmed' size='sm' ta='center' mt={5}>
            Already have an account?{' '}
            <Anchor size='sm' component='a' onClick={() => toggle('login')}>
              Sign in
            </Anchor>
          </Text>

          <Paper withBorder shadow='md' p={30} mt={30} radius='md'>
            <form
              onSubmit={registerForm.onSubmit(async (values) => {
                const id = notifications.show({
                  loading: true,
                  title: `Creating account`,
                  message: `Please wait...`,
                  autoClose: false,
                  withCloseButton: false
                });
                const registerResponse = await register({
                  first_name: values.firstName,
                  last_name: values.lastName,
                  email: values.email,
                  password: values.password
                });
                if (registerResponse) {
                  const loginResponse = await login(values.email, values.password);
                  if (loginResponse) {
                    setUser(loginResponse.user);
                    setRefreshId(refreshLoggedIn());
                    onClose();
                    notifications.update({
                      id,
                      title: `Account created`,
                      message: `Welcome ${loginResponse.user.first_name}!`,
                      color: 'green',
                      autoClose: 2000,
                      loading: false
                    });
                  } else {
                    notifications.update({
                      id,
                      title: `Unable to Login`,
                      message: `Please try again.`,
                      color: 'red',
                      autoClose: 2000,
                      loading: false
                    });
                  }
                } else {
                  notifications.update({
                    id,
                    title: `Unable to Register`,
                    message: `Please try again.`,
                    color: 'error',
                    autoClose: 2000,
                    loading: false
                  });
                }
              })}
            >
              <TextInput label='First name' placeholder='John' required {...registerForm.getInputProps('firstName')} />
              <TextInput
                label='Last name'
                placeholder='Smith'
                required
                mt='md'
                {...registerForm.getInputProps('lastName')}
              />
              <TextInput
                label='Email'
                placeholder='you@example.com'
                required
                {...registerForm.getInputProps('email')}
              />
              <PasswordInput
                label='Password'
                description='Passwords must be at least 10 characters long, contain at least one number, one uppercase letter, one lowercase letter, and one special character.'
                placeholder='Your password'
                required
                mt='md'
                {...registerForm.getInputProps('password')}
              />
              <Button type='submit' fullWidth mt='xl'>
                Sign up
              </Button>
            </form>
          </Paper>
        </Container>
      ) : (
        <Container>
          <Title ta='center'>Welcome back!</Title>
          <Text c='dimmed' size='sm' ta='center' mt={5}>
            Do not have an account yet?{' '}
            <Anchor size='sm' component='a' onClick={() => toggle('register')}>
              Create account
            </Anchor>
          </Text>

          <Paper withBorder shadow='md' p={30} mt={30} radius='md'>
            <form
              onSubmit={loginForm.onSubmit(async (values) => {
                const response = await login(values.email, values.password);
                if (response) {
                  setUser(response.user);
                  setRefreshId(refreshLoggedIn());
                  onClose();
                } else {
                  notifications.show({
                    title: `Unable to Login`,
                    message: `Please try again.`,
                    color: 'red',
                    autoClose: 2000
                  });
                }
              })}
            >
              <TextInput label='Email' placeholder='you@example.com' required {...loginForm.getInputProps('email')} />
              <PasswordInput
                label='Password'
                placeholder='Your password'
                required
                mt='md'
                {...loginForm.getInputProps('password')}
              />
              <Group justify='space-between' mt='lg'>
                <Checkbox label='Remember me' {...loginForm.getInputProps('remember')} />
                <Anchor component='a' size='sm' onClick={() => toggle('reset')}>
                  Forgot password?
                </Anchor>
              </Group>
              <Button type='submit' fullWidth mt='xl'>
                Sign in
              </Button>
            </form>
          </Paper>
        </Container>
      )}
    </Modal>
  );
}
