// Shared plumbing for the individual system-settings pages.
// Each settings page calls useSystemSettings() in its own setup, so state is
// per-page (no cross-page leak). The composable owns the load-all/save/toggle/
// upload machinery plus the static display catalogs, keeping the pages thin.
// Per-page connection-status computeds (zabbix/dell/smtp/saml) stay in the pages.
import { ref, reactive } from 'vue'
import { settingsApi, computersApi } from '../api'
import { setIdentifierFlag } from './identifierSettings'
import { apiError } from '../utils/apiError'

// Branding logo widgets. kind maps to the backend endpoint; key is the setting
// the resulting URL is stored under.
export const brandingLogos = [
  { kind: 'site', key: 'site_logo', label: 'Site logo', accept: 'image/*',
    placeholder: '/ge-aerospace-logo.svg',
    hint: 'Shown in the app header and login. Upload an image or type a path/URL.' },
  { kind: 'qr', key: 'qr_logo', label: 'QR overlay logo', accept: 'image/*',
    placeholder: '/ge-monogram.svg',
    hint: 'Logo overlaid on printed QR codes. Leave blank for no overlay.' },
  { kind: 'badge', key: 'badge_logo', label: 'Machine badge logo', accept: 'image/*',
    placeholder: '/ge-aerospace-logo.svg',
    hint: 'Logo printed on machine badges. Upload an image or type a path/URL.' },
  { kind: 'favicon', key: 'site_favicon', label: 'Favicon', accept: 'image/*,.ico',
    placeholder: '(blank = shipped /favicon.svg)',
    hint: 'Browser-tab icon. Leave blank to use the shipped favicon.' },
]

// Asset identifier matrix: identifier x asset type. Keys follow
// identifier_<name>_<assettype>_enabled. Missing = enabled (default on).
export const identifierRows = [
  { name: 'gaugelabreference', label: 'Gauge Lab Reference' },
  { name: 'maintenancereference', label: 'Maintenance Reference' },
  { name: 'fqdn', label: 'FQDN / Hostname' }
]
export const assetTypeCols = [
  { key: 'machine', label: 'Machine' },
  { key: 'computer', label: 'PC' },
  { key: 'printer', label: 'Printer' },
  { key: 'network_device', label: 'Network' },
  { key: 'measuring_tool', label: 'Measuring Tool' }
]

// Global-search domain toggles: keys follow search_<type>_enabled.
// Missing = enabled (default on).
export const searchDomains = [
  { key: 'application', label: 'Applications' },
  { key: 'knowledgebase', label: 'Knowledge Base' },
  { key: 'employee', label: 'Employees' },
  { key: 'machine', label: 'Machines' },
  { key: 'computer', label: 'PCs' },
  { key: 'printer', label: 'Printers' },
  { key: 'network_device', label: 'Network Devices' },
  { key: 'measuring_tool', label: 'Measuring Tools' },
  { key: 'notification', label: 'Notifications' },
  { key: 'subnet', label: 'Subnets' },
  { key: 'usb_device', label: 'USB Devices' },
  { key: 'printed_item', label: 'Printed Items' }
]

export function useSystemSettings() {
  // Every settings key across all pages. A page binds only its own subset.
  const settings = reactive({
    // Zabbix
    zabbix_enabled: false,
    zabbix_url: '',
    zabbix_token: '',
    // Dell warranty
    warranty_dell_enabled: false,
    warranty_dell_clientid: '',
    warranty_dell_clientsecret: '',
    warranty_dell_tokenurl: '',
    warranty_dell_apiurl: '',
    // ServiceNow
    servicenow_enabled: true,
    servicenow_search_url: '',
    servicenow_ticket_prefixes: '',
    servicenow_incident_url: '',
    servicenow_change_url: '',
    // Branding
    site_logo: '',
    qr_logo: '',
    badge_logo: '',
    site_favicon: '',
    brand_primary_color: '',
    brand_primary_dark_color: '',
    brand_accent_color: '',
    brand_sidebar_color: '',
    // Printing and labels
    qr_target_printer: '',
    qr_target_usb: '',
    usb_label_style: 'barcode',
    qr_target_machine: '',
    qr_target_computer: '',
    qr_target_network_device: '',
    qr_target_measuring_tool: '',
    label_default_style: 'card',
    label_default_codetype: 'qr',
    label_default_encodes_machine: 'assetnumber',
    label_default_encodes_computer: 'assetpage',
    label_default_encodes_printer: 'assetpage',
    label_default_encodes_network_device: 'assetpage',
    label_default_encodes_measuring_tool: 'location',
    // Email
    smtp_enabled: false,
    smtp_host: '',
    smtp_port: 587,
    smtp_username: '',
    smtp_password: '',
    smtp_use_tls: true,
    smtp_from_address: '',
    smtp_from_name: 'ShopDB',
    alert_recipients: '',
    site_base_url: '',
    alert_webhook_url: '',
    alert_webhook_format: 'teams',
    // Audit
    audit_retention_days: 90,
    // Floor map blueprint (per-facility)
    map_blueprint_light: '',
    map_blueprint_dark: '',
    map_width: 3300,
    map_height: 2550,
    // SAML
    saml_enabled: false,
    saml_idp_metadata_url: '',
    saml_entity_id: '',
    saml_acs_url: '',
    saml_allow_local_login: true,
    saml_auto_create_users: true,
    saml_admin_group: ''
  })

  const identifierMatrix = reactive({})
  const searchMatrix = reactive({})
  const pcTypeMappings = ref([])   // [{ pxetype, computertype }]
  const computerTypes = ref([])    // ComputerType names for the dropdown

  const loading = ref(true)
  const saving = ref(false)
  const mapUploading = ref(false)
  const brandingUploading = ref(false)
  const error = ref('')
  const success = ref('')

  function flashSaved() {
    success.value = 'Setting saved'
    setTimeout(() => { success.value = '' }, 2000)
  }

  function identifierKey(name, assettype) {
    return `identifier_${name}_${assettype}_enabled`
  }

  function matrixValue(name, assettype) {
    const key = identifierKey(name, assettype)
    return key in identifierMatrix ? identifierMatrix[key] : true
  }

  function searchValue(domainKey) {
    const key = `search_${domainKey}_enabled`
    return key in searchMatrix ? searchMatrix[key] : true
  }

  // Load all settings and fan them into settings / matrices / pctype rows.
  async function loadSettings() {
    try {
      loading.value = true
      const { data } = await settingsApi.list()

      const pctypeRows = []
      for (const setting of data.data) {
        if (setting.key in settings) {
          settings[setting.key] = setting.value
        } else if (/^identifier_.+_(machine|computer|printer|network_device|measuring_tool)_enabled$/.test(setting.key)) {
          identifierMatrix[setting.key] = setting.value !== false
        } else if (/^search_.+_enabled$/.test(setting.key)) {
          searchMatrix[setting.key] = setting.value !== false
        } else if (setting.key.startsWith('pctypemap_')) {
          pctypeRows.push({
            pxetype: setting.key.slice('pctypemap_'.length),
            computertype: setting.value
          })
        }
      }
      pcTypeMappings.value = pctypeRows.sort((a, b) => a.pxetype.localeCompare(b.pxetype))
    } catch (e) {
      error.value = 'Failed to load settings'
      console.error(e)
    } finally {
      loading.value = false
    }
  }

  // Computer type options for the pctype mapping dropdown (own request).
  async function loadComputerTypes() {
    try {
      const typesResponse = await computersApi.types.list({ perpage: 100 })
      computerTypes.value = (typesResponse.data.data || []).map(t => t.computertype)
    } catch (typesError) {
      console.error('Failed to load computer types', typesError)
    }
  }

  async function saveSetting(key, value) {
    try {
      saving.value = true
      error.value = ''
      success.value = ''
      await settingsApi.update(key, value)
      settings[key] = value
      flashSaved()
    } catch (e) {
      error.value = apiError(e, 'Failed to save setting')
      console.error(e)
    } finally {
      saving.value = false
    }
  }

  async function toggleSetting(key) {
    await saveSetting(key, !settings[key])
  }

  // Toggle a per-type identifier flag. The key may not be seeded on older
  // installs, so create it when the update returns 404.
  async function toggleIdentifier(name, assettype) {
    const key = identifierKey(name, assettype)
    const newValue = !matrixValue(name, assettype)
    try {
      saving.value = true
      error.value = ''
      success.value = ''
      try {
        await settingsApi.update(key, newValue)
      } catch (e) {
        if (e.response?.status === 404) {
          await settingsApi.create({
            key,
            value: newValue,
            valuetype: 'boolean',
            category: 'identifiers',
            description: `Show the ${name} identifier on ${assettype} assets`
          })
        } else {
          throw e
        }
      }
      identifierMatrix[key] = newValue
      // Push into the shared composable so open asset views react without a
      // full page reload (the composable otherwise fetches only once).
      setIdentifierFlag(name, assettype, newValue)
      flashSaved()
    } catch (e) {
      error.value = apiError(e, 'Failed to save setting')
      console.error(e)
    } finally {
      saving.value = false
    }
  }

  async function toggleSearchDomain(domainKey) {
    const key = `search_${domainKey}_enabled`
    const newValue = !searchValue(domainKey)
    const label = searchDomains.find(d => d.key === domainKey)?.label || domainKey
    try {
      saving.value = true
      error.value = ''
      success.value = ''
      try {
        await settingsApi.update(key, newValue)
      } catch (e) {
        if (e.response?.status === 404) {
          await settingsApi.create({
            key,
            value: newValue,
            valuetype: 'boolean',
            category: 'search',
            description: `Include ${label} in global search results`
          })
        } else {
          throw e
        }
      }
      searchMatrix[key] = newValue
      flashSaved()
    } catch (e) {
      error.value = apiError(e, 'Failed to save setting')
      console.error(e)
    } finally {
      saving.value = false
    }
  }

  async function changePcTypeMapping(pxetype, computertype) {
    const key = `pctypemap_${pxetype}`
    try {
      saving.value = true
      error.value = ''
      success.value = ''
      await settingsApi.update(key, computertype)
      const row = pcTypeMappings.value.find(r => r.pxetype === pxetype)
      if (row) row.computertype = computertype
      flashSaved()
    } catch (e) {
      error.value = apiError(e, 'Failed to save setting')
      console.error(e)
    } finally {
      saving.value = false
    }
  }

  async function uploadBlueprint(theme, event) {
    const file = event.target.files[0]
    if (!file) return
    mapUploading.value = true
    error.value = ''
    success.value = ''
    try {
      const { data } = await settingsApi.uploadMapBlueprint(theme, file)
      const url = data?.data?.value
      if (theme === 'light') settings.map_blueprint_light = url
      else settings.map_blueprint_dark = url
      success.value = 'Blueprint uploaded'
      setTimeout(() => { success.value = '' }, 2000)
    } catch (e) {
      error.value = apiError(e, 'Upload failed')
    } finally {
      mapUploading.value = false
      event.target.value = ''
    }
  }

  async function uploadLogo(kind, key, event) {
    const file = event.target.files[0]
    if (!file) return
    brandingUploading.value = true
    error.value = ''
    success.value = ''
    try {
      const { data } = await settingsApi.uploadBrandingLogo(kind, file)
      const url = data?.data?.value
      if (url) settings[key] = url
      success.value = 'Logo uploaded'
      setTimeout(() => { success.value = '' }, 2000)
    } catch (e) {
      error.value = apiError(e, 'Upload failed')
    } finally {
      brandingUploading.value = false
      event.target.value = ''
    }
  }

  return {
    settings,
    identifierMatrix, searchMatrix, pcTypeMappings, computerTypes,
    loading, saving, mapUploading, brandingUploading, error, success,
    loadSettings, loadComputerTypes,
    saveSetting, toggleSetting,
    identifierKey, matrixValue, toggleIdentifier,
    searchValue, toggleSearchDomain,
    changePcTypeMapping,
    uploadBlueprint, uploadLogo,
  }
}
