import {
  Button,
  Dropdown,
  Flex,
  Tag,
  Tooltip,
  Typography,
  ArrowLeftOutlined,
  BellFilled,
  BellOutlined,
  CalendarOutlined,
  DownOutlined,
  EditOutlined,
  ImportOutlined,
  SaveOutlined,
  SettingOutlined,
  SyncOutlined,
  UsergroupAddOutlined,
} from '@/shared/antd-imports';
import { PageHeader } from '@ant-design/pro-components';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { useState, useCallback, useMemo, memo, useRef, useEffect } from 'react';
import { createPortal } from 'react-dom';

import { colors } from '@/styles/colors';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { useAppSelector } from '@/hooks/useAppSelector';
import { SocketEvents } from '@/shared/socket-events';
import { useAuthService } from '@/hooks/useAuth';
import { useSocket } from '@/socket/socketContext';
import {
  setProject,
  setImportTaskTemplateDrawerOpen,
  setRefreshTimestamp,
  getProject,
} from '@features/project/project.slice';
import {
  addTask,
  fetchTaskGroups,
  fetchTaskListColumns,
  IGroupBy,
} from '@features/tasks/tasks.slice';
import ProjectStatusIcon from '@/components/common/project-status-icon/project-status-icon';
import { formatDate } from '@/utils/timeUtils';
import { toggleSaveAsTemplateDrawer } from '@/features/projects/projectsSlice';
import SaveProjectAsTemplate from '@/components/save-project-as-template/save-project-as-template';
import {
  fetchProjectData,
  toggleProjectDrawer,
  setProjectId,
} from '@/features/project/project-drawer.slice';
import { setSelectedTaskId, setShowTaskDrawer } from '@/features/task-drawer/task-drawer.slice';
import { ITaskCreateRequest } from '@/types/tasks/task-create-request.types';
import { DEFAULT_TASK_NAME, UNMAPPED } from '@/shared/constants';
import { IProjectTask } from '@/types/project/projectTasksViewModel.types';
import { getGroupIdByGroupedColumn } from '@/services/task-list/taskList.service';
import logger from '@/utils/errorLogger';
import ImportTaskTemplate from '@/components/task-templates/import-task-template';
import ProjectDrawer from '@/components/projects/project-drawer/project-drawer';
import { toggleProjectMemberDrawer } from '@/features/projects/singleProject/members/projectMembersSlice';
import useIsProjectManager from '@/hooks/useIsProjectManager';
import useTabSearchParam from '@/hooks/useTabSearchParam';
import { addTaskCardToTheTop, fetchBoardTaskGroups } from '@/features/board/board-slice';
import { fetchPhasesByProjectId } from '@/features/projects/singleProject/phase/phases.slice';
import { fetchEnhancedKanbanGroups } from '@/features/enhanced-kanban/enhanced-kanban.slice';
import { fetchTasksV3 } from '@/features/task-management/task-management.slice';

const ProjectViewHeader = memo(() => {
  const navigate = useNavigate();
  const { t } = useTranslation('project-view/project-view-header');
  const dispatch = useAppDispatch();
  const { tab } = useTabSearchParam();

  // Memoize auth service calls to prevent unnecessary re-evaluations
  const authService = useAuthService();
  const currentSession = useMemo(() => authService.getCurrentSession(), [authService]);
  const isOwnerOrAdmin = useMemo(() => authService.isOwnerOrAdmin(), [authService]);
  const isProjectManager = useIsProjectManager();

  const { socket } = useSocket();

  // Optimized selectors with shallow equality checks
  const selectedProject = useAppSelector(state => state.projectReducer.project);
  const projectId = useAppSelector(state => state.projectReducer.projectId);
  const loadingGroups = useAppSelector(state => state.taskReducer.loadingGroups);
  const groupBy = useAppSelector(state => state.taskReducer.groupBy);

  const [creatingTask, setCreatingTask] = useState(false);
  const [subscriptionLoading, setSubscriptionLoading] = useState(false);

  // Use ref to track subscription timeout
  const subscriptionTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  // Memoized refresh handler with optimized dependencies
  const handleRefresh = useCallback(() => {
    if (!projectId) return;

    dispatch(getProject(projectId));

    switch (tab) {
      case 'tasks-list':
        dispatch(fetchTaskListColumns(projectId));
        dispatch(fetchPhasesByProjectId(projectId));
        dispatch(fetchTaskGroups(projectId));
        dispatch(fetchTasksV3(projectId));
        break;
      case 'board':
        dispatch(fetchEnhancedKanbanGroups(projectId));
        break;
      case 'project-insights-member-overview':
      case 'all-attachments':
      case 'members':
      case 'updates':
        dispatch(setRefreshTimestamp());
        break;
    }
  }, [dispatch, projectId, tab]);

  // Optimized subscription handler with proper cleanup
  const handleSubscribe = useCallback(() => {
    if (!selectedProject?.id || !socket || subscriptionLoading) return;

    try {
      setSubscriptionLoading(true);
      const newSubscriptionState = !selectedProject.subscribed;

      // Clear any existing timeout
      if (subscriptionTimeoutRef.current) {
        clearTimeout(subscriptionTimeoutRef.current);
      }

      // Emit socket event
      socket.emit(SocketEvents.PROJECT_SUBSCRIBERS_CHANGE.toString(), {
        project_id: selectedProject.id,
        user_id: currentSession?.id,
        team_member_id: currentSession?.team_member_id,
        mode: newSubscriptionState ? 0 : 1,
      });

      // Listen for response with cleanup
      const handleResponse = (response: any) => {
        try {
          dispatch(
            setProject({
              ...selectedProject,
              subscribed: newSubscriptionState,
            })
          );
        } catch (error) {
          logger.error('Error handling project subscription response:', error);
          dispatch(
            setProject({
              ...selectedProject,
              subscribed: selectedProject.subscribed,
            })
          );
        } finally {
          setSubscriptionLoading(false);
          if (subscriptionTimeoutRef.current) {
            clearTimeout(subscriptionTimeoutRef.current);
            subscriptionTimeoutRef.current = null;
          }
        }
      };

      socket.once(SocketEvents.PROJECT_SUBSCRIBERS_CHANGE.toString(), handleResponse);

      // Set timeout with ref tracking
      subscriptionTimeoutRef.current = setTimeout(() => {
        setSubscriptionLoading(false);
        logger.error('Project subscription timeout - no response from server');
        subscriptionTimeoutRef.current = null;
      }, 5000);
    } catch (error) {
      logger.error('Error updating project subscription:', error);
      setSubscriptionLoading(false);
    }
  }, [selectedProject, socket, subscriptionLoading, currentSession, dispatch]);

  // Memoized settings handler
  const handleSettingsClick = useCallback(() => {
    if (selectedProject?.id) {
      dispatch(setProjectId(selectedProject.id));
      dispatch(fetchProjectData(selectedProject.id));
      dispatch(toggleProjectDrawer());
    }
  }, [dispatch, selectedProject?.id]);

  // Optimized task creation handler
  const handleCreateTask = useCallback(() => {
    if (!selectedProject?.id || !currentSession?.id || !socket) return;

    try {
      setCreatingTask(true);

      const body: Partial<ITaskCreateRequest> = {
        name: DEFAULT_TASK_NAME,
        project_id: selectedProject.id,
        reporter_id: currentSession.id,
        team_id: currentSession.team_id,
      };

      const handleTaskCreated = (task: IProjectTask) => {
        if (task.id) {
          dispatch(setSelectedTaskId(task.id));
          dispatch(setShowTaskDrawer(true));

          const groupId = groupBy === IGroupBy.PHASE ? UNMAPPED : getGroupIdByGroupedColumn(task);
          if (groupId) {
            if (tab === 'board') {
              dispatch(addTaskCardToTheTop({ sectionId: groupId, task }));
            } else {
              dispatch(addTask({ task, groupId }));
            }
            socket.emit(SocketEvents.GET_TASK_PROGRESS.toString(), task.id);
          }
        }
        setCreatingTask(false);
      };

      socket.once(SocketEvents.QUICK_TASK.toString(), handleTaskCreated);
      socket.emit(SocketEvents.QUICK_TASK.toString(), JSON.stringify(body));
    } catch (error) {
      logger.error('Error creating task', error);
      setCreatingTask(false);
    }
  }, [selectedProject?.id, currentSession, socket, dispatch, groupBy, tab]);

  // Memoized import task template handler
  const handleImportTaskTemplate = useCallback(() => {
    dispatch(setImportTaskTemplateDrawerOpen(true));
  }, [dispatch]);

  // Memoized navigation handler
  const handleNavigateToProjects = useCallback(() => {
    navigate('/worklenz/projects');
  }, [navigate]);

  // Memoized save as template handler
  const handleSaveAsTemplate = useCallback(() => {
    dispatch(toggleSaveAsTemplateDrawer());
  }, [dispatch]);

  // Memoized invite handler
  const handleInvite = useCallback(() => {
    dispatch(toggleProjectMemberDrawer());
  }, [dispatch]);

  // Memoized dropdown items
  const dropdownItems = useMemo(
    () => [
      {
        key: 'import',
        label: (
          <div style={{ width: '100%', margin: 0, padding: 0 }} onClick={handleImportTaskTemplate}>
            <ImportOutlined /> {t('importTask')}
          </div>
        ),
      },
    ],
    [handleImportTaskTemplate, t]
  );

  // Memoized project attributes with optimized date formatting
  const projectAttributes = useMemo(() => {
    if (!selectedProject) return null;

    const elements = [];

    if (selectedProject.category_id) {
      elements.push(
        <Tag
          key="category"
          color={colors.vibrantOrange}
          style={{ borderRadius: 24, paddingInline: 8, margin: 0 }}
        >
          {selectedProject.category_name}
        </Tag>
      );
    }

    if (selectedProject.status) {
      elements.push(
        <Tooltip key="status" title={selectedProject.status}>
          <ProjectStatusIcon
            iconName={selectedProject.status_icon || ''}
            color={selectedProject.status_color || ''}
          />
        </Tooltip>
      );
    }

    if (selectedProject.start_date || selectedProject.end_date) {
      const tooltipContent = (
        <Typography.Text style={{ color: colors.white }}>
          {selectedProject.start_date &&
            `${t('startDate')}: ${formatDate(new Date(selectedProject.start_date))}`}
          {selectedProject.end_date && (
            <>
              <br />
              {`${t('endDate')}: ${formatDate(new Date(selectedProject.end_date))}`}
            </>
          )}
        </Typography.Text>
      );

      elements.push(
        <Tooltip key="dates" title={tooltipContent}>
          <CalendarOutlined style={{ fontSize: 16 }} />
        </Tooltip>
      );
    }

    if (selectedProject.notes) {
      elements.push(
        <Typography.Text key="notes" type="secondary">
          {selectedProject.notes}
        </Typography.Text>
      );
    }

    return (
      <Flex gap={8} align="center">
        {elements}
      </Flex>
    );
  }, [selectedProject, t]);

  // Memoized header actions with conditional rendering optimization
  const headerActions = useMemo(() => {
    const actions = [];

    // Refresh button
    actions.push(
      <Tooltip key="refresh" title={t('refreshProject')}>
        <Button
          shape="circle"
          icon={<SyncOutlined spin={loadingGroups} />}
          onClick={handleRefresh}
        />
      </Tooltip>
    );

    // Save as template (owner/admin only)
    if (isOwnerOrAdmin) {
      actions.push(
        <Tooltip key="template" title={t('saveAsTemplate')}>
          <Button shape="circle" icon={<SaveOutlined />} onClick={handleSaveAsTemplate} />
        </Tooltip>
      );
    }

    // Settings button
    actions.push(
      <Tooltip key="settings" title={t('projectSettings')}>
        <Button shape="circle" icon={<SettingOutlined />} onClick={handleSettingsClick} />
      </Tooltip>
    );

    // Subscribe button
    actions.push(
      <Tooltip key="subscribe" title={t('subscribe')}>
        <Button
          shape="round"
          loading={subscriptionLoading}
          icon={selectedProject?.subscribed ? <BellFilled /> : <BellOutlined />}
          onClick={handleSubscribe}
        >
          {selectedProject?.subscribed ? t('unsubscribe') : t('subscribe')}
        </Button>
      </Tooltip>
    );

    // Invite button (owner/admin/project manager only)
    if (isOwnerOrAdmin || isProjectManager) {
      actions.push(
        <Button key="invite" type="primary" icon={<UsergroupAddOutlined />} onClick={handleInvite}>
          {t('invite')}
        </Button>
      );
    }

    // Create task button
    if (isOwnerOrAdmin) {
      actions.push(
        <Dropdown.Button
          key="create-task-dropdown"
          loading={creatingTask}
          type="primary"
          icon={<DownOutlined />}
          menu={{ items: dropdownItems }}
          trigger={['click']}
          onClick={handleCreateTask}
        >
          <EditOutlined /> {t('createTask')}
        </Dropdown.Button>
      );
    } else {
      actions.push(
        <Button
          key="create-task"
          loading={creatingTask}
          type="primary"
          icon={<EditOutlined />}
          onClick={handleCreateTask}
        >
          {t('createTask')}
        </Button>
      );
    }

    return (
      <Flex gap={8} align="center">
        {actions}
      </Flex>
    );
  }, [
    loadingGroups,
    handleRefresh,
    isOwnerOrAdmin,
    handleSaveAsTemplate,
    handleSettingsClick,
    t,
    subscriptionLoading,
    selectedProject?.subscribed,
    handleSubscribe,
    isProjectManager,
    handleInvite,
    creatingTask,
    dropdownItems,
    handleCreateTask,
  ]);

  // Memoized page header title
  const pageHeaderTitle = useMemo(
    () => (
      <Flex gap={8} align="center">
        <ArrowLeftOutlined style={{ fontSize: 16 }} onClick={handleNavigateToProjects} />
        <Typography.Title level={4} style={{ marginBlockEnd: 0, marginInlineStart: 12 }}>
          {selectedProject?.name}
        </Typography.Title>
        {projectAttributes}
      </Flex>
    ),
    [handleNavigateToProjects, selectedProject?.name, projectAttributes]
  );

  // Memoized page header styles
  const pageHeaderStyle = useMemo(
    () => ({
      paddingInline: 0,
      marginBlockEnd: 12,
    }),
    []
  );

  // Cleanup timeout on unmount
  useEffect(() => {
    return () => {
      if (subscriptionTimeoutRef.current) {
        clearTimeout(subscriptionTimeoutRef.current);
      }
    };
  }, []);

  return (
    <>
      <PageHeader
        className="site-page-header"
        title={pageHeaderTitle}
        style={pageHeaderStyle}
        extra={headerActions}
      />
      {createPortal(<ProjectDrawer onClose={() => {}} />, document.body, 'project-drawer')}
      {createPortal(<ImportTaskTemplate />, document.body, 'import-task-template')}
      {createPortal(<SaveProjectAsTemplate />, document.body, 'save-project-as-template')}
    </>
  );
});

ProjectViewHeader.displayName = 'ProjectViewHeader';

export default ProjectViewHeader;
