/**
 * Test setup file for Vitest
 * Configures mocks and global test utilities
 */

import { vi, beforeEach, afterEach } from 'vitest';
import '@testing-library/jest-dom/vitest';

// Polyfill for IE-specific event methods that React DOM's input polyfill checks for
// jsdom doesn't implement these, but React tries to use them for IE compatibility
if (typeof Element !== 'undefined' && !Element.prototype.attachEvent) {
  (Element.prototype as any).attachEvent = function() {};
  (Element.prototype as any).detachEvent = function() {};
}

// Mock localStorage for Zustand persist middleware
const localStorageMock = (() => {
  let store: Record<string, string> = {};
  return {
    getItem: vi.fn((key: string) => store[key] || null),
    setItem: vi.fn((key: string, value: string) => {
      store[key] = value;
    }),
    removeItem: vi.fn((key: string) => {
      delete store[key];
    }),
    clear: vi.fn(() => {
      store = {};
    }),
    get length() {
      return Object.keys(store).length;
    },
    key: vi.fn((index: number) => Object.keys(store)[index] || null),
  };
})();

Object.defineProperty(globalThis, 'localStorage', {
  value: localStorageMock,
  writable: true,
});

// Mock window.electronAPI for renderer tests
Object.defineProperty(globalThis, 'window', {
  value: {
    localStorage: localStorageMock,
    electronAPI: {
      git: {
        checkAvailability: vi.fn(),
        getRepoState: vi.fn(),
        getStatus: vi.fn(),
        getDiff: vi.fn(),
        getDiffContent: vi.fn(),
        getHistory: vi.fn(),
        getFileHistory: vi.fn(),
        init: vi.fn(),
      },
      posts: {
        create: vi.fn(),
        update: vi.fn(),
        delete: vi.fn(),
        get: vi.fn(),
        getAll: vi.fn(),
        getByStatus: vi.fn(),
        publish: vi.fn(),
        rebuildFromFiles: vi.fn(),
        search: vi.fn(),
        filter: vi.fn(),
        getTags: vi.fn(),
        getCategories: vi.fn(),
        getByYearMonth: vi.fn(),
        getLinksTo: vi.fn(),
        getLinkedBy: vi.fn(),
        rebuildLinks: vi.fn(),
      },
      media: {
        import: vi.fn(),
        importDialog: vi.fn(),
        update: vi.fn(),
        delete: vi.fn(),
        get: vi.fn(),
        getAll: vi.fn(),
        rebuildFromFiles: vi.fn(),
        getThumbnail: vi.fn(),
        regenerateThumbnails: vi.fn(),
        search: vi.fn(),
        getUrl: vi.fn(),
        getFilePath: vi.fn(),
      },
      sync: {
        checkAvailability: vi.fn(),
        getRepoState: vi.fn(),
        getStatus: vi.fn(),
        getHistory: vi.fn(),
        getRemoteState: vi.fn(),
        fetch: vi.fn(),
        pull: vi.fn(),
        push: vi.fn(),
        commitAll: vi.fn(),
      },
      dropbox: {
        configure: vi.fn(),
        isConfigured: vi.fn(),
        getStatus: vi.fn(),
        syncAll: vi.fn(),
        startWatching: vi.fn(),
        stopWatching: vi.fn(),
        startPolling: vi.fn(),
        stopPolling: vi.fn(),
        getConflicts: vi.fn(),
        resolveConflict: vi.fn(),
        getLastSyncTime: vi.fn(),
      },
      meta: {
        getTags: vi.fn(),
        getCategories: vi.fn(),
        addTag: vi.fn(),
        removeTag: vi.fn(),
        addCategory: vi.fn(),
        removeCategory: vi.fn(),
        syncOnStartup: vi.fn(),
        getProjectMetadata: vi.fn(),
        setProjectMetadata: vi.fn(),
        updateProjectMetadata: vi.fn(),
      },
      tasks: {
        getAll: vi.fn(),
        getRunning: vi.fn(),
        cancel: vi.fn(),
        clearCompleted: vi.fn(),
      },
      app: {
        triggerMenuAction: vi.fn(),
        getBlogmarkBookmarklet: vi.fn(),
        copyToClipboard: vi.fn(),
        notifyRendererReady: vi.fn(),
      },
      import: {
        selectAndAnalyze: vi.fn(),
        analyzeFile: vi.fn(),
        selectUploadsFolder: vi.fn(),
      },
      importDefinitions: {
        create: vi.fn(),
        get: vi.fn(),
        getAll: vi.fn(),
        update: vi.fn(),
        delete: vi.fn(),
      },
      templates: {
        getEnabledByKind: vi.fn().mockResolvedValue([]),
        getAll: vi.fn().mockResolvedValue([]),
        get: vi.fn().mockResolvedValue(null),
        create: vi.fn().mockResolvedValue(null),
        update: vi.fn().mockResolvedValue(null),
        delete: vi.fn().mockResolvedValue({ deleted: true }),
        validate: vi.fn().mockResolvedValue({ valid: true, errors: [] }),
        rebuildFromFiles: vi.fn().mockResolvedValue(undefined),
      },
      on: vi.fn(() => () => {}),
    },
  },
  writable: true,
});

// Mock Electron app module
vi.mock('electron', () => ({
  app: {
    getPath: vi.fn((name: string) => {
      const paths: Record<string, string> = {
        userData: '/mock/userData',
        appData: '/mock/appData',
        temp: '/mock/temp',
      };
      return paths[name] || '/mock/unknown';
    }),
    isPackaged: false,
    quit: vi.fn(),
    on: vi.fn(),
  },
  ipcMain: {
    handle: vi.fn(),
    on: vi.fn(),
    removeHandler: vi.fn(),
  },
  ipcRenderer: {
    invoke: vi.fn(),
    on: vi.fn(),
    send: vi.fn(),
  },
  BrowserWindow: vi.fn().mockImplementation(() => ({
    loadURL: vi.fn(),
    loadFile: vi.fn(),
    on: vi.fn(),
    webContents: {
      send: vi.fn(),
      openDevTools: vi.fn(),
    },
    isDestroyed: vi.fn(() => false),
  })),
  Menu: {
    buildFromTemplate: vi.fn(),
    setApplicationMenu: vi.fn(),
  },
}));

// Reset mocks between tests
beforeEach(() => {
  vi.clearAllMocks();
});

afterEach(() => {
  vi.restoreAllMocks();
});

// Global test utilities
declare global {
  // Add any global test utilities here
  var testUtils: {
    wait: (ms: number) => Promise<void>;
    createMockDate: (date: string) => Date;
  };
}

globalThis.testUtils = {
  wait: (ms: number) => new Promise(resolve => setTimeout(resolve, ms)),
  createMockDate: (date: string) => new Date(date),
};
