// @unocss-include
import { safeDirname, vue } from '@factor/api'
import type { DataFilter, IndexMeta } from '@factor/api'

import type { AdminPluginSettings } from '@factor/plugin-admin/plugin'
import { AdminPlugin } from '@factor/plugin-admin/plugin'
import { ManageIndex, ManageRegion, ManageSite } from './endpoint'
import type { TableSiteConfig } from './tables'
import { tables } from './tables'
import { Site } from './site'
import type { ToolKeys } from './el/tools'
import { tools } from './el/tools'
import { getRoutes } from './routes'
import { themes } from './themes'

export class FactorSites extends AdminPlugin {
  queries = {
    ManageSite: new ManageSite({ ...this.settings, factorSites: this }),
    ManageIndex: new ManageIndex({ ...this.settings, factorSites: this }),
    ManageRegion: new ManageRegion({ ...this.settings, factorSites: this }),
  }

  requests = this.createRequests({
    queries: this.queries,
    factorServer: this.settings.factorServer,
    factorUser: this.settings.factorUser,
  })

  constructor(settings: AdminPluginSettings) {
    const s = { ...settings, root: safeDirname(import.meta.url) }

    super('FactorSites', s)

    this.settings.factorDb.addTables(tables)

    this.settings.factorRouter?.update(getRoutes())

    this.settings.factorAdmin.views.value = [
      ...this.settings.factorAdmin.views.value,
      {
        viewId: 'sites',
        icon: 'i-tabler-layout-navbar',
        el: vue.defineAsyncComponent(() => import('./el/ViewIndex.vue')),
        settings: { isNavItem: true },
      },
      {
        viewId: 'siteEdit',
        el: vue.defineAsyncComponent(() => import('./el/SiteEditor.vue')),
        settings: { layoutFormat: 'full' },
      },
    ]
  }

  activeSite = vue.shallowRef<Site | undefined>(undefined)

  activeToolId = {
    left: vue.ref<ToolKeys | ''>(),
    right: vue.ref<ToolKeys | ''>(),
  }

  activeTool = {
    left: vue.computed(() => tools().find(t => t.toolId === this.activeToolId.left.value)),
    right: vue.computed(() => tools().find(t => t.toolId === (this.activeToolId.right.value ? this.activeToolId.right.value : 'editCard'))),
  }

  useTool(args: { toolId: ToolKeys | '' }) {
    const { toolId } = args
    const t = tools().find(t => t.toolId === toolId)
    const location = t?.location || 'left'
    this.activeToolId[location].value = toolId
  }

  isUsingTool(args: { toolId?: ToolKeys | '', locations?: ('left' | 'right')[] } = {}) {
    const { toolId, locations = ['left', 'right'] } = args
    return locations.some(l => this.activeToolId[l].value === toolId)
  }

  async loadSite(args: { siteId: string }) {
    const { siteId } = args
    this.activeSite.value = await this.requestManageSite({ fields: { siteId }, _action: 'retrieve' })
  }

  async loadSiteFromTheme(args: { themeId: string }) {
    const { themeId } = args
    const theme = themes.find(t => t.themeId === themeId)

    if (!theme)
      return

    return new Site({ factorSites: this, ...theme.toConfig() })
  }

  async requestIndex(
    args: {
      limit?: number
      offset?: number
      filters?: DataFilter[]
      imageId?: string
    } = {},
  ): Promise<{ items: Site[] | undefined, indexMeta?: IndexMeta }> {
    const { limit = 10, offset = 0 } = args || {}

    const r = await this.requests.ManageIndex.projectRequest({
      _action: 'list',
      limit,
      offset,
    })

    const items = r.data
      ? r.data.map(d => new Site({ ...d, factorSites: this }))
      : undefined

    return { items, indexMeta: r.indexMeta }
  }

  async requestManageSite(args: { fields: Partial<TableSiteConfig> & { siteId: string }, _action: 'retrieve' | 'update' | 'delete' }) {
    const { fields, _action } = args
    this.log.info(`manage site ${fields.siteId}:${_action}`)

    const r = await this.requests.ManageSite.projectRequest({
      _action,
      fields,
    })

    let out: Site | undefined = undefined
    if (r.data?.siteId)
      out = new Site({ ...r.data, factorSites: this })

    return out
  }
}
export const pluginConfig = {
  serviceId: 'factorSites',
  title: 'Sites',
  description: 'Create and manage websites',
  setup: async (settings: AdminPluginSettings): Promise<AdminPlugin> => {
    return new FactorSites(settings)
  },
}
