import { SetStateAction, useEffect, useState } from 'react';
import ContentCard from '../components/shared/ContentCard';
import {
  createNotification,
  createReadNotification,
  deleteReadNotification,
  getNotifications,
  getReadNotifications,
  Notification,
  ReadNotification,
} from '../api/Notifications';
import { ListGroup, Badge, Button, Modal, Form } from 'react-bootstrap';
import { useAuth } from '../auth/AuthProvider';
import UserDirectory from '../components/RequestForm/UserDirectory';
import { User } from '../api/Users';
import { getFormattedTeamName, getTeams, Team } from '../api/Teams';
import { Icon } from '../components/shared/Icon';
import { useMediaQuery } from 'react-responsive';
import { breakpoints } from '../utils/BootstrapHelper';
import { useToast } from '../components/Toast/ToastContext';

export const Notifications = () => {
  const { user } = useAuth();
  const [notifications, setNotifications] = useState<Notification[]>([]);
  const [readNotifications, setReadNotifications] = useState<
    ReadNotification[]
  >([]);
  const [hoveredId, setHoveredId] = useState<number | null>(null);
  const [selectedUser, setSelectedUser] = useState<User | undefined>(undefined);
  const [selectedTeamName, setSelectedTeamName] = useState<string>('');
  const [showModal, setShowModal] = useState(false);
  const [customMessage, setCustomMessage] = useState('');
  const [teams, setTeams] = useState<Team[]>([]);
  const [description, setDescription] = useState<string>('');

  const getAndSetNotifications = async () => {
    let result: SetStateAction<Notification[]>;
    if (user?.team_id) {
      result = await getNotifications(user.team_id);
    } else if (user?.type === 'instructor' || user?.type === 'ta') {
      // instructor
      const teams = await getTeams();
      setTeams(teams);
      result = await getNotifications(); // getting as instructor
      result = result.filter(
        (notification) => notification.for_instructor === true
      );
    } else {
      result = [];
    }
    setNotifications(result);

    const readResult = await getReadNotifications(user?.user_id as number);
    setReadNotifications(readResult);
  };

  useEffect(() => {
    if (user) {
      getAndSetNotifications();
    }
    setDescription(
      user?.type == 'student'
        ? 'View and manage notifications regarding updates on previously submitted requests, as well as messages from instructors and TAs.'
        : 'View and manage notifications regarding newly submitted requests, or send custom messages to students and their teams.'
    );
  }, [user]);

  useEffect(() => {
    const fetchTeamName = async () => {
      if (selectedUser?.team_id) {
        const team = teams.find(
          (team) => team.team_id === selectedUser?.team_id
        );
        setSelectedTeamName(
          getFormattedTeamName(team as Team, undefined, true)
        );
      }
    };

    fetchTeamName();
  }, [selectedUser]);

  const formatDate = (dateString: string) => {
    const options: Intl.DateTimeFormatOptions = {
      year: 'numeric',
      month: 'long',
      day: 'numeric',
      hour: 'numeric',
      minute: 'numeric',
      hour12: true,
      timeZone: 'America/New_York', // Specify EST time zone
    };

    return new Date(dateString).toLocaleDateString('en-US', options);
  };

  const getDayOnly = (dateString: string): string => {
    return new Date(dateString).toLocaleDateString('en-US', {
      year: 'numeric',
      month: 'long',
      day: 'numeric',
      timeZone: 'America/New_York',
    });
  };

  const markAsRead = async (notification_id: number) => {
    const readNotification: ReadNotification = {
      notification_id: notification_id,
      user_id: user?.user_id as number,
    };
    setReadNotifications((prev) => [...prev, readNotification]);
    await createReadNotification(readNotification);
  };

  const markAsUnread = async (notification_id: number) => {
    const readNotification = readNotifications.find(
      (notification) => notification.notification_id === notification_id
    );

    if (!readNotification) {
      //console.log('Read notification not found');
      return;
    }

    // Call the delete function to remove the read notification
    await deleteReadNotification(
      readNotification.read_notification_id as number
    );

    // Remove the notification from the state after deletion
    setReadNotifications((prev) =>
      prev.filter(
        (notification) =>
          notification.read_notification_id !==
          readNotification.read_notification_id
      )
    );
  };

  const markAsReadOrUnread = async (notification_id: number) => {
    const isAlreadyRead = isRead(notification_id);

    if (isAlreadyRead) {
      markAsUnread(notification_id);
    } else {
      markAsRead(notification_id);
    }
    getAndSetNotifications();
  };

  // Mark all notifications as read
  const markAllAsRead = async () => {
    if (!user) {
      return;
    }

    const unreadNotifications = notifications.filter(
      (notification) => !isRead(notification.notification_id as number)
    );

    const promises = unreadNotifications.map((notification) => {
      const readNotification: ReadNotification = {
        notification_id: notification.notification_id as number,
        user_id: user.user_id as number,
      };
      return createReadNotification(readNotification);
    });

    await Promise.all(promises);
    await getAndSetNotifications();
  };

  const isRead = (notification_id: number) => {
    return readNotifications.some(
      (readNotification) => readNotification.notification_id === notification_id
    );
  };

  const groupedNotifications = notifications.reduce(
    (acc, notification) => {
      const dateKey = getDayOnly(notification.notification_timestamp as string);

      if (!acc[dateKey]) {
        acc[dateKey] = [];
      }
      acc[dateKey].push(notification);
      return acc;
    },
    {} as Record<string, Notification[]>
  );

  const { addToast } = useToast();

  const sendCustomNotification = async () => {
    if (!selectedUser || !customMessage.trim()) {
      //alert('Please select a recipient and enter a message.');
      addToast('You must select a recipient and enter a message.', 'danger');
      return;
    }

    const customNotification: Notification = {
      team_id: selectedUser.team_id as number,
      generated_message: `Message from ${user?.first_name} ${user?.last_name}:`,
      free_text: customMessage,
      for_instructor: false,
    };

    await createNotification(customNotification);
    addToast('Message sent to team.', 'success');

    // Reset form
    setSelectedUser(undefined);
    setCustomMessage('');
    setShowModal(false);
  };

  const title = 'Notifications';

  const isMobileMd = useMediaQuery({ maxWidth: breakpoints.md - 1 });
  const isMobileLg = useMediaQuery({ maxWidth: breakpoints.lg - 1 });

  return (
    <ContentCard title={title} description={description} fullPage>
      <div className='row g-3'>
        {(user?.type === 'instructor' || user?.type === 'ta') && (
          <div className='col-md-6'>
            <Button
              variant='success'
              className={`${isMobileMd ? 'w-100' : ''}`}
              onClick={() => setShowModal(true)}
            >
              Send Custom Notification
            </Button>
          </div>
        )}
        <div
          className={
            user?.type === 'instructor' || user?.type === 'ta'
              ? 'col-md-6'
              : 'col-md-12'
          }
        >
          <Button
            variant='primary'
            onClick={markAllAsRead}
            className={`${isMobileMd ? 'w-100' : 'float-end'}`}
            disabled={!notifications.length}
          >
            Mark All as Read
          </Button>
        </div>
      </div>
      <hr />
      {/* Modal for sending custom notification */}
      <Modal
        show={showModal}
        onHide={() => {
          setShowModal(false);
          setSelectedUser(undefined);
        }}
      >
        <Modal.Header closeButton>
          <Modal.Title>Send Custom Notification</Modal.Title>
        </Modal.Header>
        <Modal.Body>
          <UserDirectory onSelectUser={setSelectedUser} />
          {selectedUser && (
            <div className='mb-3'>
              <p className='mb-2'>
                <strong>Selected User:</strong> {selectedUser.first_name}{' '}
                {selectedUser.last_name}, {selectedTeamName}
              </p>
              <Form.Control
                as='textarea'
                rows={3}
                placeholder='Enter notification message...'
                value={customMessage}
                onChange={(e) => setCustomMessage(e.target.value)}
              />
            </div>
          )}
        </Modal.Body>
        <Modal.Footer>
          <Button
            variant='secondary'
            onClick={() => {
              setShowModal(false);
              setSelectedUser(undefined);
            }}
          >
            Close
          </Button>
          <Button variant='primary' onClick={sendCustomNotification}>
            Send Notification
          </Button>
        </Modal.Footer>
      </Modal>
      {notifications.length ? (
        <div
          className='overflow-y-scroll'
          style={!isMobileLg ? { maxHeight: '50rem' } : undefined}
        >
          {Object.entries(groupedNotifications)
            .reverse()
            .map(([date, notifications], index) => (
              <div
                className={
                  index + 1 !== Object.keys(groupedNotifications).length
                    ? 'mb-3'
                    : ''
                }
              >
                <div className='fw-bold mb-2 ms-3'>{date}</div>
                <ListGroup>
                  {notifications.reverse().map((notification) => (
                    <ListGroup.Item
                      key={notification.notification_id}
                      className={`d-flex justify-content-between align-items-center ${
                        isRead(notification.notification_id as number)
                          ? 'text-muted bg-light'
                          : ''
                      }`}
                    >
                      <div className='me-3'>
                        {!isRead(notification.notification_id as number) && (
                          <div className='fw-bold'>
                            {notification.generated_message}
                            <div className='fw-normal'>
                              {notification.free_text}
                            </div>
                          </div>
                        )}
                        {isRead(notification.notification_id as number) && (
                          <div className='fw-normal'>
                            {notification.generated_message}
                            <div className='fw-light'>
                              {notification.free_text}
                            </div>
                          </div>
                        )}
                        {notification.notification_timestamp && (
                          <div className='text-muted small'>
                            {formatDate(notification.notification_timestamp)}
                          </div>
                        )}
                      </div>
                      <div
                        onClick={() =>
                          markAsReadOrUnread(
                            notification.notification_id as number
                          )
                        }
                        onMouseEnter={() =>
                          setHoveredId(notification.notification_id as number)
                        }
                        onMouseLeave={() => setHoveredId(null)}
                        style={{ cursor: 'pointer' }}
                      >
                        <h5>
                          <Badge
                            className='p-2'
                            bg={
                              isRead(notification.notification_id as number)
                                ? 'primary'
                                : 'danger'
                            }
                          >
                            {hoveredId === notification.notification_id
                              ? isRead(notification.notification_id)
                                ? 'Mark as unread'
                                : 'Mark as read'
                              : isRead(notification.notification_id as number)
                                ? 'Read'
                                : 'Unread'}
                          </Badge>
                        </h5>
                      </div>
                    </ListGroup.Item>
                  ))}
                </ListGroup>
              </div>
            ))}
        </div>
      ) : (
        <div className='d-flex flex-column justify-content-center align-items-center pt-3'>
          <Icon iconName='Stars' size={64} className='text-warning mb-3' />
          <p className='lead'>You have no notifications!</p>
        </div>
      )}
    </ContentCard>
  );
};
