import { describe, it, expect, beforeEach, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { useUi } from '../../stores/useUi' // Adjust path
import SettingsView from '../SettingsView.vue' // Adjust path

// No global 'store' variable here, it will be test-specific or wrapper-specific
// Helper to manage store and wrapper creation for tests
const setupTestEnvironment = (initialStoreState = {}) => {
  setActivePinia(createPinia()); // Ensures a fresh Pinia instance

  // Mock localStorage for the store if not already globally mocked by Vitest setup
  // Ensure this mock is consistent with how useUi.js uses localStorage
  const localStorageMock = (() => {
    let lsStore = { ...initialStoreState }; // Initialize with initialStoreState for loading
    return {
      getItem: vi.fn((key) => {
        const value = lsStore[key];
        // Pinia/useUi expects JSON string or null
        return typeof value === 'object' ? JSON.stringify(value) : value;
      }),
      setItem: vi.fn((key, value) => {
        // Store as string, as localStorage does
        lsStore[key] = value.toString();
        // Make actual saved string available for inspection if needed
        // This helps verify what _saveAppearanceState would do
        if (key === 'appearanceSettings') {
            lsStore['_raw_appearanceSettings'] = value.toString();
        }
      }),
      clear: vi.fn(() => { lsStore = {}; }),
      removeItem: vi.fn((key) => { delete lsStore[key]; }),
      // Helper to get the raw string for assertion
      getRawItem: (key) => lsStore[key]
    };
  })();
  Object.defineProperty(window, 'localStorage', { value: localStorageMock, writable: true });

  // If initialStoreState is provided, simulate it being in localStorage
  // The useUi store reads from localStorage upon creation.
  if (Object.keys(initialStoreState).length > 0) {
    localStorage.setItem('appearanceSettings', JSON.stringify(initialStoreState));
  } else {
    localStorage.removeItem('appearanceSettings'); // Ensure no settings if none provided
  }

  const store = useUi(); // This will now load from the mocked localStorage

  const wrapper = mount(SettingsView, {
    global: {
      // Pinia store is automatically available due to setActivePinia
    },
  });

  return { wrapper, store, localStorageMock };
};


describe('SettingsView.vue', () => {
  beforeEach(() => {
    // Vitest's vi.clearAllMocks() might be useful here if mocks persist unexpectedly
    // This setupTestEnvironment function already handles fresh store and localStorage mock per call.
    // If window.localStorage was stubbed globally (e.g. in vitest.setup.js), ensure it's reset.
    // For this example, setupTestEnvironment manages its own localStorage mock.
  });

  it('renders all input elements with initial values from store', () => {
    const { wrapper } = setupTestEnvironment({
        primaryColor: '#111111',
        secondaryColor: '#222222',
        warningColor: '#333333',
        backgroundColor: '#444444',
        fontFamily: 'Arial',
        fontSize: 18,
        animationsEnabled: false,
        theme: 'dark',
        // Add new accent colors for comprehensive initial state testing
        primaryColor: '#111111',
        secondaryColor: '#222222',
        warningColor: '#333333',
        backgroundColor: '#444444',
        fontFamily: 'Arial',
        fontSize: 18,
        animationsEnabled: false,
        theme: 'dark',
        accentColorEmpleados: '#123456',
        accentColorTareas: '#654321',
        accentColorPlanillas: '#abcdef',
        accentColorAsistencias: '#fedcba',
        accentColorConfiguracion: '#aabbcc',
        defaultViewEmpleados: 'card', // New default view
        defaultViewTareas: 'table',
        defaultViewPlanillas: 'card',
        defaultViewAsistencias: 'table',
        defaultViewConfiguracion: 'card',
    });

    expect(wrapper.find('input#primaryColor').element.value).toBe('#111111');
    expect(wrapper.find('input#secondaryColor').element.value).toBe('#222222');
    expect(wrapper.find('input#warningColor').element.value).toBe('#333333')
    expect(wrapper.find('input#backgroundColor').element.value).toBe('#444444')
    expect(wrapper.find('input#fontFamily').element.value).toBe('Arial')
    expect(wrapper.find('input#fontSize').element.value).toBe('18')
    expect(wrapper.find('input#animationsEnabled').element.checked).toBe(false);
    expect(wrapper.find('select#theme').element.value).toBe('dark');

    // Check module accent color pickers
    expect(wrapper.find('input#accentColorEmpleados').element.value).toBe('#123456');
    expect(wrapper.find('input#accentColorTareas').element.value).toBe('#654321');
    expect(wrapper.find('input#accentColorPlanillas').element.value).toBe('#abcdef');
    expect(wrapper.find('input#accentColorAsistencias').element.value).toBe('#fedcba');
    expect(wrapper.find('input#accentColorConfiguracion').element.value).toBe('#aabbcc');

    // Check new default view select elements
    expect(wrapper.find('select#defaultViewEmpleados').element.value).toBe('card');
    expect(wrapper.find('select#defaultViewTareas').element.value).toBe('table');
    expect(wrapper.find('select#defaultViewPlanillas').element.value).toBe('card');
    expect(wrapper.find('select#defaultViewAsistencias').element.value).toBe('table');
    expect(wrapper.find('select#defaultViewConfiguracion').element.value).toBe('card');
  });

  it('calls setPrimaryColor action when primary color input changes', async () => {
    const { wrapper, store } = setupTestEnvironment();
    const spy = vi.spyOn(store, 'setPrimaryColor');
    const colorInput = wrapper.find('input#primaryColor');
    colorInput.element.value = '#FF00FF';
    await colorInput.trigger('input');
    expect(spy).toHaveBeenCalledWith('#ff00ff');
  });

  it('calls setFontFamily action when font family input changes', async () => {
    const { wrapper, store } = setupTestEnvironment();
    const spy = vi.spyOn(store, 'setFontFamily');
    const input = wrapper.find('input#fontFamily');
    await input.setValue('Helvetica');
    expect(spy).toHaveBeenCalledWith('Helvetica');
  });

  it('calls setFontSize action when font size input changes', async () => {
    const { wrapper, store } = setupTestEnvironment();
    const spy = vi.spyOn(store, 'setFontSize');
    const input = wrapper.find('input#fontSize');
    await input.setValue('22');
    expect(spy).toHaveBeenCalledWith(22);
  });

  it('calls setAnimationsEnabled action when animations checkbox changes', async () => {
    const { wrapper, store } = setupTestEnvironment({ animationsEnabled: true });
    const spy = vi.spyOn(store, 'setAnimationsEnabled');
    const checkbox = wrapper.find('input#animationsEnabled');
    await checkbox.setChecked(false);
    expect(spy).toHaveBeenCalledWith(false);
  });

  it('calls setTheme action when theme select changes', async () => {
    const { wrapper, store } = setupTestEnvironment();
    const spy = vi.spyOn(store, 'setTheme');
    const select = wrapper.find('select#theme');
    await select.setValue('dark');
    expect(spy).toHaveBeenCalledWith('dark');
  });

  // Tests for module accent color pickers
  it('calls setAccentColorEmpleados action when empleados accent color input changes', async () => {
    const { wrapper, store } = setupTestEnvironment();
    const spy = vi.spyOn(store, 'setAccentColorEmpleados');
    const colorInput = wrapper.find('input#accentColorEmpleados');
    colorInput.element.value = '#aabbcc';
    await colorInput.trigger('input');
    expect(spy).toHaveBeenCalledWith('#aabbcc');
  });

  it('calls setAccentColorConfiguracion action when configuracion accent color input changes', async () => {
    const { wrapper, store } = setupTestEnvironment();
    const spy = vi.spyOn(store, 'setAccentColorConfiguracion');
    const colorInput = wrapper.find('input#accentColorConfiguracion');
    colorInput.element.value = '#ccddee';
    await colorInput.trigger('input');
    expect(spy).toHaveBeenCalledWith('#ccddee');
  });


  // *** ADD NEW TESTS FOR DEFAULT VIEW SELECTS HERE ***
  describe('Default View Selects', () => {
    it('renders default view select for Empleados module and calls action on change', async () => {
      const { wrapper, store } = setupTestEnvironment({ defaultViewEmpleados: 'table' });
      const select = wrapper.find('select#defaultViewEmpleados');
      expect(select.exists()).toBe(true);
      expect(select.element.value).toBe('table');
      const options = select.findAll('option');
      expect(options.length).toBe(2);
      expect(options[0].text()).toBe('Table');
      expect(options[0].element.value).toBe('table');
      expect(options[1].text()).toBe('Card');
      expect(options[1].element.value).toBe('card');

      const spy = vi.spyOn(store, 'setDefaultViewEmpleados');
      await select.setValue('card');
      expect(spy).toHaveBeenCalledWith('card');
      expect(select.element.value).toBe('card'); // Assuming v-model updates from store mock correctly
    });

    it('renders default view select for Tareas module and calls action on change', async () => {
      const { wrapper, store } = setupTestEnvironment({ defaultViewTareas: 'table' });
      const select = wrapper.find('select#defaultViewTareas');
      expect(select.exists()).toBe(true);
      expect(select.element.value).toBe('table');
      const spy = vi.spyOn(store, 'setDefaultViewTareas');
      await select.setValue('card');
      expect(spy).toHaveBeenCalledWith('card');
      expect(select.element.value).toBe('card');
    });

    it('renders default view select for Planillas module and calls action on change', async () => {
      const { wrapper, store } = setupTestEnvironment({ defaultViewPlanillas: 'table' });
      const select = wrapper.find('select#defaultViewPlanillas');
      expect(select.exists()).toBe(true);
      expect(select.element.value).toBe('table');
      const spy = vi.spyOn(store, 'setDefaultViewPlanillas');
      await select.setValue('card');
      expect(spy).toHaveBeenCalledWith('card');
      expect(select.element.value).toBe('card');
    });

    it('renders default view select for Asistencias module and calls action on change', async () => {
      const { wrapper, store } = setupTestEnvironment({ defaultViewAsistencias: 'table' });
      const select = wrapper.find('select#defaultViewAsistencias');
      expect(select.exists()).toBe(true);
      expect(select.element.value).toBe('table');
      const spy = vi.spyOn(store, 'setDefaultViewAsistencias');
      await select.setValue('card');
      expect(spy).toHaveBeenCalledWith('card');
      expect(select.element.value).toBe('card');
    });

    it('renders default view select for Configuracion module and calls action on change', async () => {
      const { wrapper, store } = setupTestEnvironment({ defaultViewConfiguracion: 'table' });
      const select = wrapper.find('select#defaultViewConfiguracion');
      expect(select.exists()).toBe(true);
      expect(select.element.value).toBe('table');
      const spy = vi.spyOn(store, 'setDefaultViewConfiguracion');
      await select.setValue('card');
      expect(spy).toHaveBeenCalledWith('card');
      expect(select.element.value).toBe('card');
    });
  });


  it('updates input values when store state changes programmatically', async () => {
    const { wrapper, store } = setupTestEnvironment();

    store.primaryColor = '#001122';
=======
    const wrapper = createWrapper()
    const spy = vi.spyOn(store, 'setTheme')
    const select = wrapper.find('select#theme')
    await select.setValue('dark') // .setValue on select triggers 'change'
    expect(spy).toHaveBeenCalledWith('dark')
  })

  it('updates input values when store state changes programmatically', async () => {
    const wrapper = createWrapper()

    // Test primaryColor
    store.primaryColor = '#001122'
    await wrapper.vm.$nextTick();
    expect(wrapper.find('input#primaryColor').element.value).toBe('#001122');

    store.fontFamily = 'Verdana';
    await wrapper.vm.$nextTick();
    expect(wrapper.find('input#fontFamily').element.value).toBe('Verdana');

    store.fontSize = 12;
    await wrapper.vm.$nextTick();
    expect(wrapper.find('input#fontSize').element.value).toBe('12');

    store.animationsEnabled = false;
    await wrapper.vm.$nextTick();
    expect(wrapper.find('input#animationsEnabled').element.checked).toBe(false);

    store.theme = 'dark';
    await wrapper.vm.$nextTick();
    expect(wrapper.find('select#theme').element.value).toBe('dark');

    store.accentColorEmpleados = '#998877';
    await wrapper.vm.$nextTick();
    expect(wrapper.find('input#accentColorEmpleados').element.value).toBe('#998877');

    // Test one of the new default view selects
    store.defaultViewEmpleados = 'card';
    await wrapper.vm.$nextTick();
    expect(wrapper.find('select#defaultViewEmpleados').element.value).toBe('card');
  });

  it('applies opacity transition class after mount', async () => {
    vi.useFakeTimers();
    const { wrapper } = setupTestEnvironment();
    expect(wrapper.find('.settings-view').classes()).not.toContain('opacity-100');

    vi.advanceTimersByTime(100);
    await wrapper.vm.$nextTick();
    expect(wrapper.find('.settings-view').classes()).toContain('opacity-100');
    vi.useRealTimers();
  });
});
