import React, { useState, useEffect, Fragment } from 'react';
import FullCalendar from '@fullcalendar/react'
import dayGridPlugin from '@fullcalendar/daygrid'
import interactionPlugin from '@fullcalendar/interaction'
import { useSelector, useDispatch } from 'react-redux';
import { openTaskEditDrawer, setEditableTask, fetchTasksBySection, updateIsLoading, fetchTasksByProject, editTask } from "../../../Settings/store/taskSlice";
import { Box, Text, Flex } from "@mantine/core";
import UserAvatarSingle from "../../../ui/UserAvatarSingle";
import { IconUserCircle, IconPlus, IconCheck } from "@tabler/icons-react";
import { useDisclosure } from "@mantine/hooks";
import AddTaskDrawerFromCalendar from "./AddTaskDrawerFromCalendar";
import { useParams } from 'react-router-dom';
import useTwColorByName from "../../../ui/useTwColorByName";
import CustomTooltip from "./GanttChart/CustomTaskTooltip";
import { Popover, Portal } from '@mantine/core';
import { notifications } from '@mantine/notifications';
import { hasPermission, useProjectPermissions } from "../../../ui/permissions";
import { translate } from '../../../../utils/i18n';

function renderEventContent(eventInfo) {
  const assignedUser = eventInfo.event.extendedProps.assigned_to;

  return (
    <Box px={6} py={1} w="100%" bg={eventInfo.event.backgroundColor || 'blue'} style={{ color: '#fff', borderRadius: '4px' }}>
      <Flex justify="flex-start" align="center" gap={10}>

        {assignedUser ? (
          <UserAvatarSingle user={assignedUser} size={20} />
        ) : (
          <Box
            w={20}
            h={20}
            style={{
              border: '1px dashed #fff',
              borderRadius: '50%',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
            }}
          >
            <IconUserCircle size={16} color="#fff" stroke={1.25} />
          </Box>
        )}
        <Text
          size="sm"
          title={eventInfo.event.title}
          lineClamp={1}
          style={{ flex: 1, minWidth: 0 }}
          dangerouslySetInnerHTML={{ __html: eventInfo.event.title }}
        />
      </Flex>
    </Box>
  );
}


const TaskCalendar = () => {

  const dispatch = useDispatch();
  const { loggedUserId } = useSelector((state) => state.auth.user);
  const { loggedInUser } = useSelector((state) => state.auth.session);
  const userId = loggedInUser ? loggedInUser.loggedUserId : loggedUserId;
  const { projectInfo, ordered, taskListSections, columns, isLoading } = useSelector((state) => state.settings.task);
  const projectPermissions = useProjectPermissions(projectInfo?.id);
  const { id } = useParams();
  const bgColor = useTwColorByName();
  const [hoveredEvent, setHoveredEvent] = useState(null);
  const [coords, setCoords] = useState({ x: 0, y: 0 });

  // FullCalendar all-day events use exclusive end dates (day after last visible day).
  // This ensures events render correctly and resize/drag handlers get consistent exclusive-end values.
  const addOneDay = (dateStr) => {
    const [y, m, d] = dateStr.split('-').map(Number);
    const date = new Date(y, m - 1, d);
    date.setDate(date.getDate() + 1);
    return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
  };

  const canManageOthers = hasPermission(
    loggedInUser,
    ['manage-tasks-by-others'],
    projectPermissions,
    'project'
  );

  const canEditCalendarEvent = (calEvent) => {
    if (canManageOthers) return true;
    const t = calEvent?.extendedProps?.task;
    return t && (t.createdBy_id == userId || t.assignedTo_id == userId);
  };

  const canCreateTask = hasPermission(
    loggedInUser,
    ['create-task'],
    projectPermissions,
    'project'
  );

  const formatDate = (date) => {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
  };

  // FullCalendar dayGrid reports end as exclusive (next day after the last visible day),
  // so we subtract 1 day before saving to match storage format.
  const saveCalendarDateChange = (info) => {
    const updatedByUser = loggedInUser ? loggedInUser.loggedUserId : loggedUserId;
    const newStart = formatDate(info.event.start);
    const endDate = info.event.end ? new Date(info.event.end) : null;
    if (endDate) endDate.setDate(endDate.getDate() - 1);
    const newEnd = endDate ? formatDate(endDate) : newStart;

    dispatch(editTask({
      id: info.event.id,
      data: {
        start_date: newStart,
        start_date_is_visible: 1,
        end_date: newEnd,
        end_date_is_visible: 1,
        updated_by: updatedByUser,
      },
    })).then((response) => {
      const ok = response.payload?.status === 200;
      notifications.show({
        color: ok ? 'green' : 'orange',
        title: ok ? translate('Success') : translate('Error'),
        message: translate('Date updated successfully.'),
        icon: <IconCheck />,
        autoClose: 3000,
      });
      if (!ok) info.revert();
    }).catch(() => info.revert());
  };

  const handleEventDrop = (info) => {
    if (!canEditCalendarEvent(info.event)) { info.revert(); return; }
    saveCalendarDateChange(info);
  };

  const handleEventResize = (info) => {
    if (!canEditCalendarEvent(info.event)) { info.revert(); return; }
    saveCalendarDateChange(info);
  };

  useEffect(() => {
    const fetchData = async () => {
      try {
        if (isLoading === true) {
          await dispatch(fetchTasksByProject({ id, data: {}, userId })).then((response) => {
            if (response.payload.status === 200) {
              dispatch(updateIsLoading(false))
            }
          });
        }
      } catch (err) {
        console.error("Unexpected error:", err);
      } finally {
        // dispatch(updateIsLoading( false ))
      }
    };
    fetchData();
  }, [dispatch, isLoading]);

  const events = Object.values(columns).flatMap(column =>
    column.map(task => {
      let barColor = undefined;

      if (task.internal_status && task.internal_status.color_code) {
        barColor = task.internal_status.color_code;
      } else if (task.statusName && task.status_color_code) {
        barColor = task.status_color_code;
      } else if (task.status === 'COMPLETED') {
        barColor = '#10B981';
      }

      if (!barColor && task.priority && task.priority.color_code) {
        barColor = task.priority.color_code;
      }

      if (!barColor && task.assigned_to && task.assigned_to.name) {
        barColor = bgColor(task.assigned_to.name)["bg-color"];
      }

      if (!barColor) {
        barColor = bgColor(String(task.id || task.name || 'default'))["bg-color"];
      }

      return {
        id: task.id,
        title: task.name,
        start: task.start_date,
        end: task.end_date ? addOneDay(task.end_date) : null,
        assigned_to: task.assigned_to,
        task: task,
        backgroundColor: barColor
      };
    })
  );

  const [task, setTask] = useState(null);
  const onEventClick = (arg) => {
    const { start, end, id, title, extendedProps } = arg.event
    //previous state replace current state using callback
    setTask({ ...extendedProps.task });

    // openTaskEditDrawer();
    dispatch(setEditableTask(extendedProps.task))
    dispatch(openTaskEditDrawer())
  }


  const [taskAddDrawerOpenFromCalendar, { open: openTaskAddDrawerFromCalendar, close: closeTaskAddDrawerFromCalendar }] = useDisclosure(false);


  const [startDate, setStartDate] = useState(null);
  const [endDate, setEndDate] = useState(null);
  const onCellSelect = (event) => {
    if (!canCreateTask) {
      notifications.show({
        color: 'orange',
        title: translate('Permission Denied'),
        message: translate('You do not have permission to create tasks.'),
        autoClose: 3000,
      });
      return;
    }
    const { startStr, endStr } = event
    if (startStr && endStr) {
      setStartDate(startStr);
      setEndDate(endStr);
      openTaskAddDrawerFromCalendar();
    }
  }

  const handleMouseEnter = (info) => {
    setHoveredEvent(info.event.extendedProps.task);
    setCoords({
      x: info.jsEvent.clientX,
      y: info.jsEvent.clientY,
    });
  };

  const handleMouseLeave = () => {
    setHoveredEvent(null);
  };

  return (
    <Fragment>
      <style>{`
        .lazytask-calendar .fc-daygrid-event {
          cursor: pointer;
          transition: box-shadow 0.15s ease;
        }
        .lazytask-calendar .fc-daygrid-event:hover {
          box-shadow: 0 0 0 2px rgba(255,255,255,0.85) inset, 0 2px 8px rgba(0,0,0,0.18);
          z-index: 5 !important;
        }
        .lazytask-calendar .fc-event-resizer {
          opacity: 0;
          transition: opacity 0.15s ease;
          width: 10px !important;
          display: flex !important;
          align-items: center;
          justify-content: center;
        }
        .lazytask-calendar .fc-daygrid-event:hover .fc-event-resizer {
          opacity: 1;
        }
        .lazytask-calendar .fc-event-resizer-start::after,
        .lazytask-calendar .fc-event-resizer-end::after {
          content: '';
          display: block;
          width: 5px;
          height: 82%;
          background: #e53e3e;
          border-radius: 3px;
        }
      `}</style>
      <div className={`lazytask-calendar${!canCreateTask ? ' no-create' : ''}`}>
      <FullCalendar
        eventClick={onEventClick}
        select={onCellSelect}
        selectable
        dayMaxEventRows={3}
        datesSet={(arg) => {
        }}
        plugins={[dayGridPlugin, interactionPlugin]}
        initialView='dayGridMonth'
        weekends={true}
        events={events}
        eventContent={renderEventContent}
        eventMouseEnter={handleMouseEnter}
        eventMouseLeave={handleMouseLeave}
        editable={true}
        eventAllow={(_, draggedEvent) => canEditCalendarEvent(draggedEvent)}
        eventDrop={handleEventDrop}
        eventResize={handleEventResize}
        eventResizableFromStart={true}
        eventDurationEditable={true}
        eventStartEditable={true}
        headerToolbar={{
          left: "title",
          right: "today prev,next",
        }}
        aspectRatio={2}
      />
      </div>
      {hoveredEvent && (
        <Portal>
          <Popover
            opened={!!hoveredEvent}
            position="top"
            withArrow
            shadow="md"
            offset={10}
            zIndex={10000}
            middlewares={{ shift: true, flip: true }}
          >
            <Popover.Target>
              <Box
                style={{
                  position: 'fixed',
                  top: coords.y,
                  left: coords.x,
                  width: 1,
                  height: 1,
                  pointerEvents: 'none',
                }}
              />
            </Popover.Target>
            <Popover.Dropdown p={0} style={{ border: 'none', background: 'transparent' }}>
              <CustomTooltip task={hoveredEvent} />
            </Popover.Dropdown>
          </Popover>
        </Portal>
      )}
      {projectInfo && startDate && <AddTaskDrawerFromCalendar startDate={startDate} endDate={endDate} project={projectInfo} taskAddDrawerOpen={taskAddDrawerOpenFromCalendar} openTaskAddDrawer={openTaskAddDrawerFromCalendar} closeTaskAddDrawer={closeTaskAddDrawerFromCalendar} />}
    </Fragment>
  );
};

export default TaskCalendar;




