/**
 * State Validity Tests After Actions
 *
 * This test suite verifies that every state-changing action maintains
 * valid state by checking:
 * 1. Typia schema validation (type correctness)
 * 2. Cross-model relationship validation (referential integrity)
 * 3. Entity state consistency (ids array matches entities object)
 *
 * The goal is to ensure no action can produce an invalid state.
 */
import { Action, ActionReducer } from '@ngrx/store';
import {
  createValidAppData,
  createValidTask,
  createValidProject,
  createValidTag,
  createValidNote,
  validateAppData,
  appDataToRootState,
  rootStateToAppData,
  createAppDataWithTask,
  createAppDataWithSubtasks,
  addTaskToAppData,
  addProjectToAppData,
  addTagToAppData,
} from './state-validity-test-utils';
import { AppDataComplete } from '../model/model-config';
import { RootState } from '../../root-store/root-state';
import { TaskSharedActions } from '../../root-store/meta/task-shared.actions';
import { WorkContextType } from '../../features/work-context/work-context.model';
import { addSubTask, moveSubTask } from '../../features/tasks/store/task.actions';
import {
  addProject,
  updateProject,
  archiveProject,
} from '../../features/project/store/project.actions';
import { addTag, updateTag, deleteTag } from '../../features/tag/store/tag.actions';
import { addNote } from '../../features/note/store/note.actions';
import {
  taskSharedCrudMetaReducer,
  taskSharedLifecycleMetaReducer,
  taskSharedSchedulingMetaReducer,
  projectSharedMetaReducer,
  tagSharedMetaReducer,
  plannerSharedMetaReducer,
} from '../../root-store/meta/task-shared-meta-reducers';
import { OpLog } from '../../core/log';
import { getDbDateStr } from '../../util/get-db-date-str';
import { TaskWithSubTasks } from '../../features/tasks/task.model';
import {
  projectReducer,
  PROJECT_FEATURE_NAME,
} from '../../features/project/store/project.reducer';
import { tagReducer, TAG_FEATURE_NAME } from '../../features/tag/store/tag.reducer';
import { taskReducer, TASK_FEATURE_NAME } from '../../features/tasks/store/task.reducer';
import { noteReducer, NOTE_FEATURE_NAME } from '../../features/note/store/note.reducer';
import {
  menuTreeReducer,
  menuTreeFeatureKey,
} from '../../features/menu-tree/store/menu-tree.reducer';
import {
  plannerReducer,
  plannerFeatureKey,
} from '../../features/planner/store/planner.reducer';
import {
  boardsReducer,
  BOARDS_FEATURE_NAME,
} from '../../features/boards/store/boards.reducer';
import {
  globalConfigReducer,
  CONFIG_FEATURE_NAME,
} from '../../features/config/store/global-config.reducer';
import {
  timeTrackingReducer,
  TIME_TRACKING_FEATURE_KEY,
} from '../../features/time-tracking/store/time-tracking.reducer';
import {
  MenuTreeKind,
  MenuTreeProjectNode,
  MenuTreeTagNode,
} from '../../features/menu-tree/store/menu-tree.model';

describe('State Validity After Actions', () => {
  // Suppress OpLog output during tests
  beforeAll(() => {
    spyOn(OpLog, 'log');
    spyOn(OpLog, 'error');
    spyOn(OpLog, 'warn');
    spyOn(OpLog, 'err');
    spyOn(OpLog, 'critical');
  });

  /**
   * Creates a base reducer that combines all feature reducers.
   */
  const createFeatureReducer = (): ActionReducer<RootState, Action> => {
    return (state: RootState | undefined, action: Action): RootState => {
      if (!state) {
        return state as unknown as RootState;
      }
      return {
        ...state,
        [TASK_FEATURE_NAME]: taskReducer(state[TASK_FEATURE_NAME], action),
        [PROJECT_FEATURE_NAME]: projectReducer(state[PROJECT_FEATURE_NAME], action),
        [TAG_FEATURE_NAME]: tagReducer(state[TAG_FEATURE_NAME], action),
        [NOTE_FEATURE_NAME]: noteReducer(state[NOTE_FEATURE_NAME], action),
        [menuTreeFeatureKey]: menuTreeReducer(state[menuTreeFeatureKey], action),
        [plannerFeatureKey]: plannerReducer(state[plannerFeatureKey], action),
        [BOARDS_FEATURE_NAME]: boardsReducer(state[BOARDS_FEATURE_NAME], action),
        [CONFIG_FEATURE_NAME]: globalConfigReducer(state[CONFIG_FEATURE_NAME], action),
        [TIME_TRACKING_FEATURE_KEY]: timeTrackingReducer(
          state[TIME_TRACKING_FEATURE_KEY],
          action,
        ),
      } as RootState;
    };
  };

  /**
   * Creates a combined reducer that applies all meta-reducers on top of feature reducers.
   */
  const createCombinedReducer = (): ActionReducer<RootState, Action> => {
    let combined: ActionReducer<RootState, Action> = createFeatureReducer();
    combined = taskSharedCrudMetaReducer(combined);
    combined = taskSharedLifecycleMetaReducer(combined);
    combined = taskSharedSchedulingMetaReducer(combined);
    combined = projectSharedMetaReducer(combined);
    combined = tagSharedMetaReducer(combined);
    combined = plannerSharedMetaReducer(combined);
    return combined;
  };

  /**
   * Helper to apply an action and validate the resulting state.
   */
  const applyActionAndValidate = (
    appData: AppDataComplete,
    action: Action,
    additionalData: Parameters<typeof rootStateToAppData>[1] = {},
  ): {
    newAppData: AppDataComplete;
    validationResult: ReturnType<typeof validateAppData>;
  } => {
    const rootState = appDataToRootState(appData);
    const reducer = createCombinedReducer();
    const newRootState = reducer(rootState, action);
    const newAppData = rootStateToAppData(newRootState, {
      ...additionalData,
      // Preserve archive states which aren't in RootState
      archiveYoung: appData.archiveYoung,
      archiveOld: appData.archiveOld,
      simpleCounter: appData.simpleCounter,
      taskRepeatCfg: appData.taskRepeatCfg,
      issueProvider: appData.issueProvider,
      metric: appData.metric,
      reminders: appData.reminders,
      pluginUserData: appData.pluginUserData,
      pluginMetadata: appData.pluginMetadata,
    });
    const validationResult = validateAppData(newAppData);
    return { newAppData, validationResult };
  };

  describe('Initial State Validation', () => {
    it('should have a valid initial state from createValidAppData', () => {
      const appData = createValidAppData();
      const result = validateAppData(appData);
      expect(result.isValid).toBe(true);
      if (!result.isValid) {
        fail(`Initial state is invalid: ${result.error}`);
      }
    });

    it('should have a valid state from createAppDataWithTask', () => {
      const appData = createAppDataWithTask();
      const result = validateAppData(appData);
      expect(result.isValid).toBe(true);
      if (!result.isValid) {
        fail(`State with task is invalid: ${result.error}`);
      }
    });

    it('should have a valid state from createAppDataWithSubtasks', () => {
      const appData = createAppDataWithSubtasks();
      const result = validateAppData(appData);
      expect(result.isValid).toBe(true);
      if (!result.isValid) {
        fail(`State with subtasks is invalid: ${result.error}`);
      }
    });
  });

  describe('TaskSharedActions', () => {
    describe('addTask', () => {
      it('should produce valid state when adding a task to a project', () => {
        const appData = createValidAppData();
        const newTask = createValidTask('newTask1', {
          projectId: 'INBOX',
          tagIds: [],
        });

        const action = TaskSharedActions.addTask({
          task: newTask,
          workContextId: 'INBOX',
          workContextType: WorkContextType.PROJECT,
          isAddToBacklog: false,
          isAddToBottom: false,
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`addTask produced invalid state: ${validationResult.error}`);
        }
      });

      it('should produce valid state when adding a task to a tag', () => {
        const baseData = createValidAppData();
        const tag = createValidTag('myTag');
        const appData = addTagToAppData(baseData, tag);

        const newTask = createValidTask('newTask1', {
          projectId: undefined,
          tagIds: ['myTag'],
        });

        const action = TaskSharedActions.addTask({
          task: newTask,
          workContextId: 'myTag',
          workContextType: WorkContextType.TAG,
          isAddToBacklog: false,
          isAddToBottom: false,
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`addTask to tag produced invalid state: ${validationResult.error}`);
        }
      });

      it('should produce valid state when adding a task to backlog', () => {
        const appData = createValidAppData();
        const newTask = createValidTask('newTask1', {
          projectId: 'INBOX',
          tagIds: [],
        });

        const action = TaskSharedActions.addTask({
          task: newTask,
          workContextId: 'INBOX',
          workContextType: WorkContextType.PROJECT,
          isAddToBacklog: true,
          isAddToBottom: false,
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`addTask to backlog produced invalid state: ${validationResult.error}`);
        }
      });

      it('should produce valid state when adding task with dueDay (today)', () => {
        const appData = createValidAppData();
        const today = getDbDateStr();
        const newTask = createValidTask('newTask1', {
          projectId: 'INBOX',
          tagIds: [],
          dueDay: today,
        });

        const action = TaskSharedActions.addTask({
          task: newTask,
          workContextId: 'INBOX',
          workContextType: WorkContextType.PROJECT,
          isAddToBacklog: false,
          isAddToBottom: false,
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`addTask with dueDay produced invalid state: ${validationResult.error}`);
        }
      });
    });

    describe('updateTask', () => {
      it('should produce valid state when updating task title', () => {
        const appData = createAppDataWithTask('task1', 'INBOX');

        const action = TaskSharedActions.updateTask({
          task: { id: 'task1', changes: { title: 'Updated Title' } },
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`updateTask produced invalid state: ${validationResult.error}`);
        }
      });

      it('should produce valid state when marking task as done', () => {
        const appData = createAppDataWithTask('task1', 'INBOX');

        const action = TaskSharedActions.updateTask({
          task: { id: 'task1', changes: { isDone: true } },
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`updateTask (isDone) produced invalid state: ${validationResult.error}`);
        }
      });

      it('should produce valid state when updating time estimate', () => {
        const appData = createAppDataWithTask('task1', 'INBOX');

        const action = TaskSharedActions.updateTask({
          task: { id: 'task1', changes: { timeEstimate: 3600000 } },
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(
            `updateTask (timeEstimate) produced invalid state: ${validationResult.error}`,
          );
        }
      });
    });

    describe('deleteTask', () => {
      it('should produce valid state when deleting a task', () => {
        const appData = createAppDataWithTask('task1', 'INBOX');
        const task = appData.task.entities['task1']!;

        const action = TaskSharedActions.deleteTask({
          task: task as TaskWithSubTasks,
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`deleteTask produced invalid state: ${validationResult.error}`);
        }
      });

      it('should produce valid state when deleting a task with subtasks', () => {
        const appData = createAppDataWithSubtasks('parent1', ['sub1', 'sub2'], 'INBOX');
        const parentTask = appData.task.entities['parent1']!;
        const sub1 = appData.task.entities['sub1']!;
        const sub2 = appData.task.entities['sub2']!;

        const taskWithSubtasks: TaskWithSubTasks = {
          ...parentTask,
          subTasks: [sub1, sub2],
        };

        const action = TaskSharedActions.deleteTask({
          task: taskWithSubtasks,
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(
            `deleteTask with subtasks produced invalid state: ${validationResult.error}`,
          );
        }
      });
    });

    describe('planTasksForToday', () => {
      it('should produce valid state when planning task for today', () => {
        const appData = createAppDataWithTask('task1', 'INBOX');

        const action = TaskSharedActions.planTasksForToday({
          taskIds: ['task1'],
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`planTasksForToday produced invalid state: ${validationResult.error}`);
        }
      });
    });

    describe('removeTasksFromTodayTag', () => {
      it('should produce valid state when removing task from today', () => {
        // First create state with task in TODAY tag
        const baseData = createAppDataWithTask('task1', 'INBOX');
        const appData = {
          ...baseData,
          task: {
            ...baseData.task,
            entities: {
              ...baseData.task.entities,
              task1: {
                ...baseData.task.entities['task1']!,
                dueDay: getDbDateStr(),
              },
            },
          },
          tag: {
            ...baseData.tag,
            entities: {
              ...baseData.tag.entities,
              TODAY: {
                ...baseData.tag.entities['TODAY']!,
                taskIds: ['task1'],
              },
            },
          },
        };

        const action = TaskSharedActions.removeTasksFromTodayTag({
          taskIds: ['task1'],
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(
            `removeTasksFromTodayTag produced invalid state: ${validationResult.error}`,
          );
        }
      });
    });

    describe('addTagToTask', () => {
      it('should produce valid state when adding tag to task', () => {
        const baseData = createAppDataWithTask('task1', 'INBOX');
        const tag = createValidTag('myTag');
        const appData = addTagToAppData(baseData, tag);

        const action = TaskSharedActions.addTagToTask({
          tagId: 'myTag',
          taskId: 'task1',
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`addTagToTask produced invalid state: ${validationResult.error}`);
        }
      });
    });

    describe('moveToOtherProject', () => {
      it('should produce valid state when moving task to another project', () => {
        const baseData = createAppDataWithTask('task1', 'INBOX');
        const newProject = createValidProject('project2');
        const appData = addProjectToAppData(baseData, newProject);
        const task = appData.task.entities['task1']!;

        const action = TaskSharedActions.moveToOtherProject({
          task: task as TaskWithSubTasks,
          targetProjectId: 'project2',
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`moveToOtherProject produced invalid state: ${validationResult.error}`);
        }
      });
    });

    describe('convertToMainTask', () => {
      it('should produce valid state when converting subtask to main task', () => {
        const appData = createAppDataWithSubtasks('parent1', ['sub1', 'sub2'], 'INBOX');
        const subtask = appData.task.entities['sub1']!;

        const action = TaskSharedActions.convertToMainTask({
          task: subtask,
          parentTagIds: [],
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`convertToMainTask produced invalid state: ${validationResult.error}`);
        }
      });
    });
  });

  describe('Task Actions (from task.actions.ts)', () => {
    describe('addSubTask', () => {
      it('should produce valid state when adding a subtask', () => {
        const appData = createAppDataWithTask('parent1', 'INBOX');
        const subTask = createValidTask('sub1', {
          projectId: 'INBOX',
          parentId: 'parent1',
        });

        const action = addSubTask({
          task: subTask,
          parentId: 'parent1',
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`addSubTask produced invalid state: ${validationResult.error}`);
        }
      });
    });

    describe('moveSubTask', () => {
      it('should produce valid state when moving subtask within same parent', () => {
        const appData = createAppDataWithSubtasks(
          'parent1',
          ['sub1', 'sub2', 'sub3'],
          'INBOX',
        );

        const action = moveSubTask({
          taskId: 'sub3',
          srcTaskId: 'parent1',
          targetTaskId: 'parent1',
          afterTaskId: 'sub1',
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`moveSubTask produced invalid state: ${validationResult.error}`);
        }
      });
    });
  });

  describe('Project Actions', () => {
    describe('addProject', () => {
      it('should produce valid state when adding a project', () => {
        const appData = createValidAppData();
        const newProject = createValidProject('project2');

        const action = addProject({ project: newProject });

        // Note: addProject doesn't update menuTree via meta-reducer
        // so we need to manually add it to make it valid
        const { newAppData } = applyActionAndValidate(appData, action);

        // Since the meta-reducer doesn't handle menuTree, we need to update it
        const newProjectNode: MenuTreeProjectNode = {
          k: MenuTreeKind.PROJECT,
          id: 'project2',
        };
        const updatedAppData = {
          ...newAppData,
          menuTree: {
            ...newAppData.menuTree,
            projectTree: [...newAppData.menuTree.projectTree, newProjectNode],
          },
        };

        const validationResult = validateAppData(updatedAppData);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`addProject produced invalid state: ${validationResult.error}`);
        }
      });
    });

    describe('updateProject', () => {
      it('should produce valid state when updating project title', () => {
        const appData = createValidAppData();

        const action = updateProject({
          project: { id: 'INBOX', changes: { title: 'Updated Inbox' } },
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`updateProject produced invalid state: ${validationResult.error}`);
        }
      });
    });

    describe('archiveProject', () => {
      it('should produce valid state when archiving a project', () => {
        const baseData = createValidAppData();
        const project = createValidProject('project2');
        const appData = addProjectToAppData(baseData, project);

        const action = archiveProject({ id: 'project2' });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`archiveProject produced invalid state: ${validationResult.error}`);
        }
      });
    });
  });

  describe('Tag Actions', () => {
    describe('addTag', () => {
      it('should produce valid state when adding a tag', () => {
        const appData = createValidAppData();
        const newTag = createValidTag('newTag');

        const action = addTag({ tag: newTag });

        const { newAppData } = applyActionAndValidate(appData, action);

        // Since the meta-reducer doesn't handle menuTree, we need to update it
        const newTagNode: MenuTreeTagNode = {
          k: MenuTreeKind.TAG,
          id: 'newTag',
        };
        const updatedAppData = {
          ...newAppData,
          menuTree: {
            ...newAppData.menuTree,
            tagTree: [...newAppData.menuTree.tagTree, newTagNode],
          },
        };

        const validationResult = validateAppData(updatedAppData);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`addTag produced invalid state: ${validationResult.error}`);
        }
      });
    });

    describe('updateTag', () => {
      it('should produce valid state when updating tag title', () => {
        const baseData = createValidAppData();
        const tag = createValidTag('myTag');
        const appData = addTagToAppData(baseData, tag);

        const action = updateTag({
          tag: { id: 'myTag', changes: { title: 'Updated Tag' } },
        });

        const { validationResult } = applyActionAndValidate(appData, action);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`updateTag produced invalid state: ${validationResult.error}`);
        }
      });
    });

    describe('deleteTag', () => {
      it('should produce valid state when deleting a tag with no tasks', () => {
        const baseData = createValidAppData();
        const tag = createValidTag('myTag');
        const appData = addTagToAppData(baseData, tag);

        const action = deleteTag({ id: 'myTag' });

        const { newAppData } = applyActionAndValidate(appData, action);

        // After deleting tag, we need to remove it from menuTree too
        const updatedAppData = {
          ...newAppData,
          menuTree: {
            ...newAppData.menuTree,
            tagTree: newAppData.menuTree.tagTree.filter(
              (node: any) => node.id !== 'myTag',
            ),
          },
        };

        const validationResult = validateAppData(updatedAppData);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`deleteTag produced invalid state: ${validationResult.error}`);
        }
      });

      it('should produce valid state when deleting a tag that has tasks', () => {
        // Create a tag with tasks
        const baseData = createValidAppData();
        const tag = createValidTag('myTag');
        let appData = addTagToAppData(baseData, tag);

        // Add a task with the tag
        const task = createValidTask('task1', {
          projectId: 'INBOX',
          tagIds: ['myTag'],
        });
        appData = addTaskToAppData(appData, task);

        // Also add task to project
        appData = {
          ...appData,
          project: {
            ...appData.project,
            entities: {
              ...appData.project.entities,
              INBOX: {
                ...appData.project.entities['INBOX']!,
                taskIds: ['task1'],
              },
            },
          },
        };

        const action = deleteTag({ id: 'myTag' });

        const { newAppData } = applyActionAndValidate(appData, action);

        // After deleting tag, remove from menuTree
        const updatedAppData = {
          ...newAppData,
          menuTree: {
            ...newAppData.menuTree,
            tagTree: newAppData.menuTree.tagTree.filter(
              (node: any) => node.id !== 'myTag',
            ),
          },
        };

        const validationResult = validateAppData(updatedAppData);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`deleteTag with tasks produced invalid state: ${validationResult.error}`);
        }
      });
    });
  });

  describe('Note Actions', () => {
    describe('addNote', () => {
      it('should produce valid state when adding a note to a project', () => {
        const appData = createValidAppData();
        const newNote = createValidNote('note1', 'INBOX');

        const action = addNote({ note: newNote });

        const { newAppData, validationResult } = applyActionAndValidate(appData, action);

        expect(validationResult.isValid).toBe(true);
        expect(newAppData.note.ids).toContain('note1');
        expect(newAppData.note.entities.note1).toEqual(newNote);
      });
    });
  });

  describe('Complex Scenarios', () => {
    describe('Multiple operations', () => {
      it('should maintain valid state after adding multiple tasks', () => {
        const baseAppData = createValidAppData();

        // Add first task
        const task1 = createValidTask('task1', { projectId: 'INBOX' });
        const action1 = TaskSharedActions.addTask({
          task: task1,
          workContextId: 'INBOX',
          workContextType: WorkContextType.PROJECT,
          isAddToBacklog: false,
          isAddToBottom: false,
        });

        const { newAppData: afterTask1 } = applyActionAndValidate(baseAppData, action1);
        const result1 = validateAppData(afterTask1);
        expect(result1.isValid).toBe(true);

        // Add second task
        const task2 = createValidTask('task2', { projectId: 'INBOX' });
        const action2 = TaskSharedActions.addTask({
          task: task2,
          workContextId: 'INBOX',
          workContextType: WorkContextType.PROJECT,
          isAddToBacklog: false,
          isAddToBottom: false,
        });

        const { newAppData: afterTask2 } = applyActionAndValidate(afterTask1, action2);
        const result2 = validateAppData(afterTask2);
        expect(result2.isValid).toBe(true);

        // Add third task
        const task3 = createValidTask('task3', { projectId: 'INBOX' });
        const action3 = TaskSharedActions.addTask({
          task: task3,
          workContextId: 'INBOX',
          workContextType: WorkContextType.PROJECT,
          isAddToBacklog: false,
          isAddToBottom: false,
        });

        const { validationResult } = applyActionAndValidate(afterTask2, action3);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`After adding 3 tasks: ${validationResult.error}`);
        }
      });

      it('should maintain valid state when adding and deleting tasks', () => {
        const baseAppData = createValidAppData();

        // Add task
        const task = createValidTask('task1', { projectId: 'INBOX' });
        const addAction = TaskSharedActions.addTask({
          task,
          workContextId: 'INBOX',
          workContextType: WorkContextType.PROJECT,
          isAddToBacklog: false,
          isAddToBottom: false,
        });

        const { newAppData: afterAdd } = applyActionAndValidate(baseAppData, addAction);
        expect(validateAppData(afterAdd).isValid).toBe(true);

        // Delete task
        const taskEntity = afterAdd.task.entities['task1']!;
        const deleteAction = TaskSharedActions.deleteTask({
          task: taskEntity as TaskWithSubTasks,
        });

        const { validationResult } = applyActionAndValidate(afterAdd, deleteAction);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`After add and delete: ${validationResult.error}`);
        }
      });

      it('should maintain valid state with task, project, and tag operations', () => {
        const baseAppData = createValidAppData();

        // Add a new project
        const newProject = createValidProject('project2');
        const withProject = addProjectToAppData(baseAppData, newProject);

        // Add a new tag
        const newTag = createValidTag('myTag');
        const withProjectAndTag = addTagToAppData(withProject, newTag);

        // Verify state is valid after manual additions
        expect(validateAppData(withProjectAndTag).isValid).toBe(true);

        // Add task to the new project with the new tag
        const task = createValidTask('task1', {
          projectId: 'project2',
          tagIds: ['myTag'],
        });
        const addAction = TaskSharedActions.addTask({
          task,
          workContextId: 'project2',
          workContextType: WorkContextType.PROJECT,
          isAddToBacklog: false,
          isAddToBottom: false,
        });

        const { validationResult } = applyActionAndValidate(withProjectAndTag, addAction);
        expect(validationResult.isValid).toBe(true);
        if (!validationResult.isValid) {
          fail(`After complex operations: ${validationResult.error}`);
        }
      });
    });
  });
});
