import {describe, expect, beforeEach, it} from 'vitest'
import {createStore} from 'vuex'
import {store} from '@store/modules/proxy/index.js'
// import {store as services} from '@store/modules/proxy/index.js'
import {addedSite, updatedSite, removedNewSite, deletedSite} from '@store/modules/proxy/helpers.js'

const sites = store.state.sites
const selectedSite = store.state.selectedSite
const isSaveData = store.state.isSaveData
const routes = store.state.routes
const routesState = store.state.routesState

const setSites = store.mutations.setSites
const setSelectedSite = store.mutations.setSelectedSite
const setIsSaveData = store.mutations.setIsSaveData
const setRoutes = store.mutations.setRoutes
const setRoutesState = store.mutations.setRoutesState

const addNewSiteLayout = store.actions.addNewSiteLayout
const createNewSite = store.actions.createNewSite
const breakeAddingSite = store.actions.breakeAddingSite
const editSelectedSite = store.actions.editSelectedSite
const saveSite = store.actions.saveSite
const breakSavingSite = store.actions.breakSavingSite
const removeSite = store.actions.removeSite
const resetStore = store.actions.resetStore

// const store = createStore({
//   plugins: [],
//   modules: {
//     services
//   },
// })

const defaultSites = [ {
  "id": 1,
  "created_at": "2024-02-22T17:08:37.715772388+03:00",
  "updated_at": "2024-02-26T14:11:38.64094899+03:00",
  "deleted_at": null,
  "name": "jsonplaceholder.typicode.com",
  "port": 9965,
  "proxy_ip": "172.25.78.153",
  "site_ip": "172.25.78.153",
  "device_ip": "172.25.78.153",
  "internet_uri": "localhost",
  "description": "localhost",
  "is_online": true
},
{
  "id": 2,
  "created_at": "0001-01-01T00:00:00Z",
  "updated_at": "2024-02-27T17:53:14.070484767+03:00",
  "deleted_at": null,
  "name": "new",
  "port": 3645,
  "proxy_ip": "172.25.78.151",
  "site_ip": "172.25.78.151",
  "device_ip": "172.25.78.151",
  "internet_uri": "",
  "description": "create... upd...",
  "is_online": true
},
{
  "id": 3,
  "created_at": "2024-02-26T17:50:07.191225008+03:00",
  "updated_at": "2024-02-28T09:41:49.274089436+03:00",
  "deleted_at": null,
  "name": "new",
  "port": 3645,
  "proxy_ip": "172.25.78.151",
  "site_ip": "172.25.78.151",
  "device_ip": "172.25.78.151",
  "internet_uri": "",
  "description": "new updated...",
  "is_online": false
}]

const mockStore = createStore({
  state: {
    sites: sites,
    selectedSite: selectedSite,
    isSaveData: isSaveData,
    routes: routes,
    routesState: routesState,
  },
  getters: {
    sites: (state) => state.sites,
    selectedSite: (state) => state.selectedSite,
  },
  mutations: {
    setSites: setSites,
    setSelectedSite: setSelectedSite,
    setIsSaveData: setIsSaveData,
    setRoutes: setRoutes,
    setRoutesState: setRoutesState
  },
  actions: {
    addNewSiteLayout: addNewSiteLayout,
    createNewSite: createNewSite,
    breakeAddingSite: breakeAddingSite,
    editSelectedSite: editSelectedSite,
    saveSite: saveSite,
    breakSavingSite: breakSavingSite,
    removeSite: removeSite,
    resetStore
  },
})

describe('mutations', () => {
  
  it('Set to empty Services', () => {
    const state = { sites: sites }
    setSites(state, null)
    expect(state.sites).to.equal(null)
  })
  
  it('Add new Service', () => {
    const newSite = {
      "id": 34,
      "created_at": "2024-02-28T15:32:21.187767309+03:00",
      "updated_at": "2024-02-28T15:32:50.820118413+03:00",
      "deleted_at": null,
      "name": "Test site 10",
      "port": 7575,
      "proxy_ip": "172.25.78.151",
      "site_ip": "172.25.78.151",
      "internet_uri": "",
      "description": "10 test create",
      "is_online": true
    }
    const updatedSites = [...sites, newSite]
    const state = { sites: sites }
    setSites(state, updatedSites)
    expect(state.sites[0]).to.toMatchObject({"name": "Test site 10", "port": 7575, "id": 34, "is_online": true})
  })
})

describe('actions', () => {
  
  it('action addNewSiteLayout - added fields for new Service', async () => {
    mockStore.dispatch('addNewSiteLayout')
    expect(mockStore.state.sites[0]).toMatchObject({id: -1})
  })
  
  it('action editSelectedSite - edited fields values in selected site', async () => {
    beforeEach(() => {
      mockStore.dispatch('resetStore')
    })
    mockStore.commit('setSelectedSite', {id: 7, name: 'custom test name', port: 3333, description: 'default'}) // added params - key, vakue for selected site
    mockStore.dispatch('editSelectedSite', {key: 'name', value: 'edited test name'})
    mockStore.dispatch('editSelectedSite', {key: 'port', value: 5555})
    mockStore.dispatch('editSelectedSite', {key: 'description', value: 'updated'})
    expect(mockStore.state.selectedSite).toMatchObject({name: 'edited test name', port: 5555, description: 'updated'})
  })
  
  it('action editSelectedSite - edited fields empty values in selected site', async () => {
    beforeEach(() => {
      mockStore.dispatch('resetStore')
    })
    mockStore.commit('setSelectedSite', {id: 7, name: '', port: '', description: ''}) // added params - key, vakue for selected site
    mockStore.dispatch('editSelectedSite', {key: 'name', value: ''})
    mockStore.dispatch('editSelectedSite', {key: 'port', value: ''})
    mockStore.dispatch('editSelectedSite', {key: 'description', value: ''})
    expect(mockStore.state.selectedSite).toMatchObject({name: '', port: '', description: ''})
  })
  
  it('action breakSavingSite - cleared selected site, replaced to default status routesState', async () => {
    beforeEach(() => {
      mockStore.dispatch('resetStore')
    })
    mockStore.commit('setSelectedSite', {id: 9, name: 'custom test name', port: 3333, description: 'default'}) // added params - key, vakue for selected site
    mockStore.commit('setRoutesState', 'active') // added status for RoutesState

    expect(mockStore.state.routesState).toBe('active') // check RoutesState status

    mockStore.dispatch('breakSavingSite', {key: 'name', value: 'edited test name'})
    expect(mockStore.state.selectedSite).toBeNull()
    expect(mockStore.state.routesState).toBe('await')
  })
  
  it('action resetStore - cleared all values in store', async () => {
    beforeEach(() => {
      mockStore.dispatch('resetStore')
    })
    
    expect(mockStore.state.selectedSite).toBeNull() // check default statuses
    expect(mockStore.state.routesState).toBe('await') // check default statuses
    expect(mockStore.state.isSaveData).toBe(false) // check default statuses

    mockStore.commit('setSelectedSite', {id: 9, name: 'custom test name', port: 3333, description: 'default'}) // added params - key, vakue for selected site
    mockStore.commit('setRoutesState', 'active') // updated status for RoutesState
    mockStore.commit('setIsSaveData', true) // updated status for isSaveData

    expect(mockStore.state.selectedSite).toMatchObject({id: 9, name: 'custom test name', port: 3333, description: 'default'}) // check updated statuses
    expect(mockStore.state.routesState).toBe('active') // check updated statuses
    expect(mockStore.state.isSaveData).toBe(true) // check updated statuses

    mockStore.dispatch('resetStore')
    expect(mockStore.state.selectedSite).toBeNull() // again check default statuses
    expect(mockStore.state.routesState).toBe('await') // again check default statuses
    expect(mockStore.state.isSaveData).toBe(false) // again check default statuses
  })

})

describe('helpers', () => {
  
  it('added new site', async () => {
    beforeEach(() => {
      mockStore.dispatch('resetStore')
    })

    const newSite = {
      "id": 34,
      "created_at": "2024-02-28T15:32:21.187767309+03:00",
      "updated_at": "2024-02-28T15:32:50.820118413+03:00",
      "deleted_at": null,
      "name": "new site 9",
      "port": 7475,
      "proxy_ip": "172.25.78.151",
      "site_ip": "172.25.78.151",
      "internet_uri": "",
      "description": "9 create",
      "is_online": true
    }
    mockStore.commit('setSites', defaultSites)
    const updatedSites = addedSite(newSite, mockStore.state.sites)
    mockStore.commit('setRoutes', updatedSites)
    const addedNewSite = mockStore.state.routes.find(route => route.id === 34)
    expect(addedNewSite).not.toBe(undefined)
    expect(addedNewSite).toMatchObject(newSite)
    
  })
  
  it('updated site', async () => {
    beforeEach(() => {
      mockStore.dispatch('resetStore')
    })

    const editedSite = {
      "id": 3,
      "created_at": "2024-02-26T17:50:07.191225008+03:00",
      "updated_at": "2024-02-28T09:41:49.274089436+03:00",
      "deleted_at": null,
      "name": "edited test name",
      "port": 5555,
      "proxy_ip": "172.25.78.151",
      "site_ip": "172.25.78.151",
      "internet_uri": "",
      "description": "new updated... updated site",
      "is_online": true
    }

    mockStore.commit('setSites', defaultSites)
    const currentSiteBeforeEdit = mockStore.state.sites.find(site => site.id === 3)
    expect(currentSiteBeforeEdit).toMatchObject({name: 'new', port: 3645, description: 'new updated...'}) // default params site
    const updatedSites = updatedSite(editedSite, mockStore.state.sites)
    mockStore.commit('setSites', updatedSites)
    const updatedSiteToStore = mockStore.state.sites.find(site => site.id === 3)
    expect(updatedSiteToStore).not.toBe(undefined)
    expect(updatedSiteToStore).toMatchObject(editedSite)
  })
  
  it('updated site - empty params', async () => {
    beforeEach(() => {
      mockStore.dispatch('resetStore')
    })

    const editedSite = {
      "id": 3,
      "created_at": "2024-02-26T17:50:07.191225008+03:00",
      "updated_at": "2024-02-28T09:41:49.274089436+03:00",
      "deleted_at": null,
      "name": "",
      "port": null,
      "proxy_ip": "172.25.78.151",
      "site_ip": "172.25.78.151",
      "internet_uri": "",
      "description": "",
      "is_online": true
    }

    mockStore.commit('setSites', defaultSites)
    const currentSiteBeforeEdit = mockStore.state.sites.find(site => site.id === 3)
    expect(currentSiteBeforeEdit).toMatchObject({name: 'new', port: 3645, description: 'new updated...'}) // default params site
    const updatedSites = updatedSite(editedSite, mockStore.state.sites)
    mockStore.commit('setSites', updatedSites)
    const updatedSiteToStore = mockStore.state.sites.find(site => site.id === 3)
    expect(updatedSiteToStore).not.toBe(undefined)
    expect(updatedSiteToStore).toMatchObject(editedSite)
  })
  
  it('removed new site before saving to server', async () => {
    beforeEach(() => {
      mockStore.dispatch('resetStore')
    })

    const newSite = {"port": "", "name": "", id: -1}

    mockStore.commit('setSites', defaultSites)
    const sitesWithNewSite = addedSite(newSite, mockStore.state.sites)
    mockStore.commit('setSites', sitesWithNewSite)
    const currentSiteBeforeDelete = mockStore.state.sites[0]
    expect(currentSiteBeforeDelete).toMatchObject({id: -1}) // default id for new site if this not saving to server
    const updatedSites = removedNewSite(mockStore.state.sites)
    mockStore.commit('setSites', updatedSites)
    const removedSiteToStore = mockStore.state.sites.find(site => site.id === -1)
    expect(removedSiteToStore).toBe(undefined) // removed site to be undefined in array sites to store
  })
  
  it('deleted selected site before saving to server', async () => {
    beforeEach(() => {
      mockStore.dispatch('resetStore')
    })

    const deleteSiteId = 3

    mockStore.commit('setSites', defaultSites)
    const currentSiteBeforeDelete = mockStore.state.sites.find(site => site.id === 3)
    expect(currentSiteBeforeDelete).toMatchObject({id: 3}) // exists site before deleteting
    const updatedSites = deletedSite(deleteSiteId, mockStore.state.sites)
    mockStore.commit('setSites', updatedSites)
    const deletedSiteToStore = mockStore.state.sites.find(site => site.id === 3)
    expect(deletedSiteToStore).toBe(undefined) // deleted site to be undefined in array sites to store
  })

})

// describe('class Services', () => {
//   it('upload Sites', async () => {
//     // const services = new Services(import.meta.env.VITE_API_ADDR, config)
//     const equalService = [{
//       "id": 1,
//       "created_at": "2024-02-22T17:08:37.715772388+03:00",
//       "updated_at": "2024-02-26T14:11:38.64094899+03:00",
//       "deleted_at": null,
//       "name": "jsonplaceholder.typicode.com",
//       "port": 9965,
//       "proxy_ip": "172.25.78.153",
//       "site_ip": "172.25.78.153",
//       "internet_uri": "localhost",
//       "description": "localhost",
//       "is_online": true
//     }]

//     vi.fn(axios.get).mockResolvedValue({
//       data: equalService,
//     })

//     const services = new Services(import.meta.env.VITE_API_ADDR, config)
//     const uploadedServices = await services.getServices()

//     mockStore.dispatch('uploadSites')
//     expect(uploadedServices[0]).to.toMatchObject(equalService[0])
//   })
// })
