import React, { act } from 'react';
import { createRoot } from 'react-dom/client';

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import type { GlobalTask } from '../../../../src/shared/types';

const storeState = {
  openGlobalTaskDetail: vi.fn(),
  teamByName: {} as Record<string, { members: unknown[] }>,
};

let unreadCountValue = 0;
let isLightValue = false;

vi.mock('../../../../src/renderer/store', () => ({
  useStore: (selector: (state: typeof storeState) => unknown) => selector(storeState),
}));

vi.mock('../../../../src/renderer/hooks/useUnreadCommentCount', () => ({
  useUnreadCommentCount: () => unreadCountValue,
}));

vi.mock('../../../../src/renderer/hooks/useTheme', () => ({
  useTheme: () => ({
    theme: isLightValue ? 'light' : 'dark',
    resolvedTheme: isLightValue ? 'light' : 'dark',
    isDark: !isLightValue,
    isLight: isLightValue,
  }),
}));

vi.mock('@features/localization/renderer', () => ({
  useAppTranslation: (namespace: string) => {
    const catalogs: Record<string, Record<string, string>> = {
      common: {
        'tasks.date.updatedPrefix': 'upd',
        'tasks.date.updatedYesterday': 'upd yesterday',
        'tasks.date.yesterday': 'Yesterday',
        'tasks.reviewState.needsFix': 'Needs Fixes',
      },
      team: {
        'tasks.teamPrefix': 'Team:',
        'tasks.unassigned': 'Unassigned',
      },
    };

    return {
      resolvedLanguage: 'en',
      t: (key: string) => catalogs[namespace]?.[key] ?? key,
    };
  },
}));

vi.mock('../../../../src/renderer/components/ui/tooltip', () => ({
  Tooltip: ({ children }: React.PropsWithChildren) =>
    React.createElement(React.Fragment, null, children),
  TooltipTrigger: ({ children }: React.PropsWithChildren) =>
    React.createElement(React.Fragment, null, children),
  TooltipContent: ({ children }: React.PropsWithChildren) =>
    React.createElement(React.Fragment, null, children),
}));

vi.mock('../../../../src/renderer/constants/teamColors', () => ({
  getTeamColorSet: () => ({ text: '#fff', textLight: '#000' }),
}));

vi.mock('../../../../src/renderer/utils/memberHelpers', () => ({
  buildMemberColorMap: () => new Map<string, string>(),
  REVIEW_STATE_DISPLAY: {
    needsFix: { bg: 'bg-red-500/10', text: 'text-red-300', label: 'Needs fix' },
  },
}));

vi.mock('../../../../src/renderer/utils/projectColor', () => ({
  nameColorSet: () => ({ text: '#fff' }),
  projectColor: () => ({ text: '#fff' }),
}));

vi.mock('../../../../src/renderer/utils/taskGrouping', () => ({
  projectLabelFromPath: () => 'hookplex',
}));

vi.mock('../../../../src/shared/utils/reviewState', () => ({
  getTaskKanbanColumn: () => 'todo',
}));

vi.mock('zustand/react/shallow', () => ({
  useShallow: <T>(selector: T) => selector,
}));

vi.mock('lucide-react', () => {
  const Icon = (props: React.SVGProps<SVGSVGElement>) => React.createElement('svg', props);
  return {
    CheckCircle2: Icon,
    Circle: Icon,
    Eye: Icon,
    Loader2: Icon,
    ShieldCheck: Icon,
    Trash2: Icon,
  };
});

import { SidebarTaskItem } from '../../../../src/renderer/components/sidebar/SidebarTaskItem';

function makeTask(overrides: Partial<GlobalTask> = {}): GlobalTask {
  return {
    id: 'task-1',
    displayId: 'task1',
    teamName: 'alpha-team',
    teamDisplayName: 'Alpha Team',
    subject: 'Review docs',
    description: '',
    status: 'in_progress',
    owner: 'alice',
    createdAt: '2026-04-18T10:00:00.000Z',
    updatedAt: '2026-04-18T10:10:00.000Z',
    reviewState: 'none',
    reviewNotes: [],
    blockedBy: [],
    blocks: [],
    comments: [],
    attachments: [],
    workIntervals: [],
    kanbanColumnId: null,
    projectPath: '/workspace/hookplex',
    ...overrides,
  } as GlobalTask;
}

describe('SidebarTaskItem unread styling', () => {
  beforeEach(() => {
    unreadCountValue = 0;
    isLightValue = false;
    storeState.openGlobalTaskDetail.mockReset();
    storeState.teamByName = {};
  });

  afterEach(() => {
    document.body.innerHTML = '';
  });

  it('uses the softened unread background tint in dark theme', async () => {
    unreadCountValue = 2;
    isLightValue = false;
    vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);

    const host = document.createElement('div');
    document.body.appendChild(host);
    const root = createRoot(host);

    await act(async () => {
      root.render(React.createElement(SidebarTaskItem, { task: makeTask() }));
      await Promise.resolve();
    });

    const button = host.querySelector('button');
    expect(button?.className).toContain('bg-blue-500/[0.05]');
    expect(button?.className).not.toContain('bg-blue-500/[0.08]');

    await act(async () => {
      root.unmount();
      await Promise.resolve();
    });
  });

  it('animates the in-progress status icon', async () => {
    vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);

    const host = document.createElement('div');
    document.body.appendChild(host);
    const root = createRoot(host);

    await act(async () => {
      root.render(React.createElement(SidebarTaskItem, { task: makeTask() }));
      await Promise.resolve();
    });

    expect(host.querySelector('svg')?.getAttribute('class')).toContain('animate-spin');

    await act(async () => {
      root.unmount();
      await Promise.resolve();
    });
  });

  it('pauses the in-progress status icon when the task team is offline', async () => {
    vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);

    const host = document.createElement('div');
    document.body.appendChild(host);
    const root = createRoot(host);

    await act(async () => {
      root.render(React.createElement(SidebarTaskItem, { task: makeTask(), teamOffline: true }));
      await Promise.resolve();
    });

    expect(host.querySelector('svg')?.getAttribute('class')).not.toContain('animate-spin');

    await act(async () => {
      root.unmount();
      await Promise.resolve();
    });
  });

  it('can hide the project label when the parent already groups by project', async () => {
    vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);

    const host = document.createElement('div');
    document.body.appendChild(host);
    const root = createRoot(host);

    await act(async () => {
      root.render(
        React.createElement(SidebarTaskItem, { task: makeTask(), hideProjectName: true })
      );
      await Promise.resolve();
    });

    expect(host.textContent).not.toContain('hookplex');
    expect(host.textContent).toContain('alice');

    await act(async () => {
      root.unmount();
      await Promise.resolve();
    });
  });

  it('renders translated updated and review labels instead of i18n keys', async () => {
    vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);

    const host = document.createElement('div');
    document.body.appendChild(host);
    const root = createRoot(host);

    const updatedAt = new Date();
    const createdAt = new Date(updatedAt.getTime() - 5 * 60_000);

    await act(async () => {
      root.render(
        React.createElement(SidebarTaskItem, {
          task: makeTask({
            createdAt: createdAt.toISOString(),
            reviewState: 'needsFix',
            updatedAt: updatedAt.toISOString(),
          }),
        })
      );
      await Promise.resolve();
    });

    expect(host.textContent).toContain('upd');
    expect(host.textContent).toContain('Needs Fixes');
    expect(host.textContent).not.toContain('tasks.date.updatedPrefix');
    expect(host.textContent).not.toContain('tasks.reviewState.needsFix');

    await act(async () => {
      root.unmount();
      await Promise.resolve();
    });
  });
});
