import { computed, onMounted, reactive, ref, watch } from 'vue'

import { ApiRequestError, api } from '../../lib/api'
import { clearSiteStatusCache } from '../../lib/siteStatus'
import type { AdminOperationalSettingsResponse } from '../../types/awards'
import type { AdminOperationalSettingsForm, AdminSettingsStatusSummary } from './adminSettingsTypes'

const fallbackMaintenanceTitle = 'Sternenpause'
const fallbackMaintenanceMessage = 'Die Award-Galaxie wird gerade liebevoll poliert. Schau gleich wieder vorbei.'

export function useAdminOperationalSettings() {
  const operationalLoading = ref(true)
  const operationalSaving = ref(false)
  const operationalError = ref('')
  const operationalSuccess = ref('')
  const demoPasswordSet = ref(false)
  const demoManagedByDatabase = ref(false)
  const demoPasswordInput = ref('')
  const twitchClientSecretSet = ref(false)
  const twitchAuthConfigured = ref(false)
  const twitchAuthManagedByDatabase = ref(false)
  const twitchClientSecretInput = ref('')
  const savedOperationalSnapshot = ref('')

  const operationalForm = reactive<AdminOperationalSettingsForm>({
    demoLoginEnabled: false,
    demoLoginIdentifier: '',
    demoLoginTwitchUserId: '',
    demoLoginDisplayName: '',
    twitchClientId: '',
    twitchRedirectUri: '',
    twitchScope: '',
    sessionIdleTimeoutHours: 3,
    maintenanceModeEnabled: false,
    maintenanceTitle: fallbackMaintenanceTitle,
    maintenanceMessage: fallbackMaintenanceMessage,
  })

  const demoPasswordHint = computed(() => {
    if (demoPasswordInput.value.trim()) {
      return 'Dieses neue Passwort wird beim Speichern gesetzt.'
    }

    if (demoPasswordSet.value) {
      return demoManagedByDatabase.value
        ? 'Passwort ist gesetzt. Leer lassen, wenn es bleiben soll.'
        : 'Aktuell kommt das Passwort aus der Demo-Config. Beim Speichern wird es in die DB übernommen.'
    }

    return 'Noch kein Demo-Passwort gesetzt. Zum Aktivieren bitte ein Passwort vergeben.'
  })

  const demoCredentialsComplete = computed(() =>
    !operationalForm.demoLoginEnabled
    || (
      Boolean(operationalForm.demoLoginIdentifier.trim())
      && Boolean(operationalForm.demoLoginTwitchUserId.trim())
      && Boolean(operationalForm.demoLoginDisplayName.trim())
      && (demoPasswordSet.value || Boolean(demoPasswordInput.value.trim()))
    ),
  )

  const twitchAuthComplete = computed(() =>
    Boolean(operationalForm.twitchClientId.trim())
    && (twitchClientSecretSet.value || Boolean(twitchClientSecretInput.value.trim()))
  )

  const twitchSecretHint = computed(() => {
    if (twitchClientSecretInput.value.trim()) {
      return 'Dieses neue Secret wird beim Speichern gesetzt.'
    }

    if (twitchClientSecretSet.value) {
      return 'Client Secret ist gesetzt. Leer lassen, wenn es bleiben soll.'
    }

    return 'Noch kein Client Secret gesetzt. Beim ersten Speichern erforderlich.'
  })

  const operationalSummary = computed<AdminSettingsStatusSummary[]>(() => [
    {
      label: 'Demo Login',
      value: operationalForm.demoLoginEnabled ? 'Aktiv' : 'Aus',
      note: operationalForm.demoLoginEnabled
        ? demoCredentialsComplete.value
          ? 'Öffentlicher Zugriff ist geschützt.'
          : 'Aktivierung braucht vollständige Zugangsdaten.'
        : 'Landingpage ist öffentlich erreichbar.',
      tone: operationalForm.demoLoginEnabled
        ? demoCredentialsComplete.value ? 'warning' : 'danger'
        : 'good',
    },
    {
      label: 'Session Timeout',
      value: `${operationalForm.sessionIdleTimeoutHours}h`,
      note: `Logout nach ${operationalForm.sessionIdleTimeoutHours} Stunden ohne Aktivitaet.`,
      tone: operationalForm.sessionIdleTimeoutHours >= 3 ? 'good' : 'danger',
    },
    {
      label: 'Wartungsmodus',
      value: operationalForm.maintenanceModeEnabled ? 'Aktiv' : 'Aus',
      note: operationalForm.maintenanceModeEnabled
        ? 'Besucher sehen die Wartungsseite.'
        : 'Öffentliche Seiten werden normal ausgeliefert.',
      tone: operationalForm.maintenanceModeEnabled ? 'warning' : 'good',
    },
    {
      label: 'Twitch OAuth',
      value: twitchAuthConfigured.value ? 'Konfiguriert' : 'Fehlt',
      note: twitchAuthConfigured.value
        ? twitchAuthManagedByDatabase.value ? 'Quelle: Datenbank' : 'Quelle: App-Konfiguration'
        : 'Offizieller Twitch Login ist noch nicht aktiv.',
      tone: twitchAuthConfigured.value ? 'good' : 'warning',
    },
    {
      label: 'Passwort',
      value: demoPasswordSet.value ? 'Gesetzt' : 'Fehlt',
      note: demoManagedByDatabase.value ? 'Quelle: Datenbank' : 'Quelle: App-Konfiguration',
      tone: demoPasswordSet.value ? 'good' : 'warning',
    },
  ])

  const hasUnsavedOperationalChanges = computed(() =>
    Boolean(savedOperationalSnapshot.value) &&
    buildOperationalSnapshot() !== savedOperationalSnapshot.value,
  )

  function applyOperationalSettings(response: AdminOperationalSettingsResponse) {
    operationalForm.demoLoginEnabled = response.demoLoginEnabled
    operationalForm.demoLoginIdentifier = response.demoLoginEmail
    operationalForm.demoLoginTwitchUserId = response.demoLoginTwitchUserId
    operationalForm.demoLoginDisplayName = response.demoLoginDisplayName
    operationalForm.twitchClientId = response.twitchClientId
    operationalForm.twitchRedirectUri = response.twitchRedirectUri
    operationalForm.twitchScope = response.twitchScope
    operationalForm.sessionIdleTimeoutHours = response.sessionIdleTimeoutHours
    operationalForm.maintenanceModeEnabled = response.maintenanceModeEnabled
    operationalForm.maintenanceTitle = response.maintenanceTitle
    operationalForm.maintenanceMessage = response.maintenanceMessage
    demoPasswordSet.value = response.demoLoginPasswordSet
    demoManagedByDatabase.value = response.demoLoginManagedByDatabase
    twitchClientSecretSet.value = response.twitchClientSecretSet
    twitchAuthConfigured.value = response.twitchAuthConfigured
    twitchAuthManagedByDatabase.value = response.twitchAuthManagedByDatabase
    demoPasswordInput.value = ''
    twitchClientSecretInput.value = ''
    rememberSavedOperationalSettings()
  }

  function buildOperationalSnapshot() {
    return JSON.stringify({
      demoLoginEnabled: operationalForm.demoLoginEnabled,
      demoLoginIdentifier: operationalForm.demoLoginIdentifier,
      demoLoginTwitchUserId: operationalForm.demoLoginTwitchUserId,
      demoLoginDisplayName: operationalForm.demoLoginDisplayName,
      twitchClientId: operationalForm.twitchClientId,
      twitchRedirectUri: operationalForm.twitchRedirectUri,
      twitchScope: operationalForm.twitchScope,
      sessionIdleTimeoutHours: operationalForm.sessionIdleTimeoutHours,
      twitchClientSecretInput: twitchClientSecretInput.value,
      maintenanceModeEnabled: operationalForm.maintenanceModeEnabled,
      maintenanceTitle: operationalForm.maintenanceTitle,
      maintenanceMessage: operationalForm.maintenanceMessage,
      demoPasswordInput: demoPasswordInput.value,
    })
  }

  function rememberSavedOperationalSettings() {
    savedOperationalSnapshot.value = buildOperationalSnapshot()
  }

  async function loadOperationalSettings(options: { silent?: boolean } = {}) {
    if (!options.silent) {
      operationalLoading.value = true
      operationalError.value = ''
    }

    try {
      applyOperationalSettings(await api.getAdminOperationalSettings())
    } catch (error) {
      operationalError.value = error instanceof ApiRequestError
        ? error.message
        : 'Operational Settings konnten nicht geladen werden.'
    } finally {
      if (!options.silent) {
        operationalLoading.value = false
      }
    }
  }

  function validateOperationalSettings() {
    if (demoPasswordInput.value.trim() && demoPasswordInput.value.trim().length < 10) {
      operationalError.value = 'Das Demo-Passwort muss mindestens 10 Zeichen lang sein.'
      return false
    }

    if (operationalForm.demoLoginEnabled && !demoCredentialsComplete.value) {
      operationalError.value = 'Demo-Login braucht Login, Twitch-ID, Anzeigenamen und ein gesetztes Passwort.'
      return false
    }

    const hasAnyTwitchAuthInput = Boolean(
      operationalForm.twitchClientId.trim()
      || operationalForm.twitchRedirectUri.trim()
      || operationalForm.twitchScope.trim()
      || twitchClientSecretInput.value.trim()
      || twitchClientSecretSet.value,
    )

    if (hasAnyTwitchAuthInput && !operationalForm.twitchClientId.trim()) {
      operationalError.value = 'Twitch OAuth braucht eine Client-ID.'
      return false
    }

    if (operationalForm.twitchClientId.trim() && !twitchAuthComplete.value) {
      operationalError.value = 'Twitch OAuth braucht beim ersten Speichern ein Client Secret.'
      return false
    }

    if (!Number.isInteger(operationalForm.sessionIdleTimeoutHours) || operationalForm.sessionIdleTimeoutHours < 3) {
      operationalError.value = 'Session-Timeout muss mindestens 3 Stunden betragen.'
      return false
    }

    return true
  }

  async function saveOperationalSettings() {
    operationalError.value = ''
    operationalSuccess.value = ''

    if (!validateOperationalSettings()) {
      return
    }

    operationalSaving.value = true
    try {
      const result = await api.updateAdminOperationalSettings({
        ...operationalForm,
        demoLoginEmail: operationalForm.demoLoginIdentifier,
        demoLoginPassword: demoPasswordInput.value.trim() || undefined,
        twitchClientSecret: twitchClientSecretInput.value.trim() || undefined,
      })

      demoPasswordSet.value = result.demoLoginPasswordSet
      demoManagedByDatabase.value = true
      twitchClientSecretSet.value = result.twitchClientSecretSet
      demoPasswordInput.value = ''
      twitchClientSecretInput.value = ''
      await loadOperationalSettings({ silent: true })
      clearSiteStatusCache()
      operationalSuccess.value = 'Demo-Zugang, Session-Timeout und Wartungsmodus wurden gespeichert.'
    } catch (error) {
      operationalError.value = error instanceof ApiRequestError
        ? error.message
        : 'Operational Settings konnten nicht gespeichert werden.'
    } finally {
      operationalSaving.value = false
    }
  }

  watch(
    () => [
      operationalForm.demoLoginEnabled,
      operationalForm.demoLoginIdentifier,
      operationalForm.demoLoginTwitchUserId,
      operationalForm.demoLoginDisplayName,
      operationalForm.twitchClientId,
      operationalForm.twitchRedirectUri,
      operationalForm.twitchScope,
      operationalForm.sessionIdleTimeoutHours,
      twitchClientSecretInput.value,
      operationalForm.maintenanceModeEnabled,
      operationalForm.maintenanceTitle,
      operationalForm.maintenanceMessage,
      demoPasswordInput.value,
    ],
    () => {
      if (operationalLoading.value || operationalSaving.value) return
      operationalError.value = ''
      operationalSuccess.value = ''
    },
  )

  onMounted(loadOperationalSettings)

  return {
    operationalLoading,
    operationalSaving,
    operationalError,
    operationalSuccess,
    operationalForm,
    demoPasswordSet,
    demoManagedByDatabase,
    demoPasswordInput,
    twitchClientSecretSet,
    twitchAuthConfigured,
    twitchAuthManagedByDatabase,
    twitchClientSecretInput,
    demoPasswordHint,
    twitchSecretHint,
    demoCredentialsComplete,
    twitchAuthComplete,
    operationalSummary,
    hasUnsavedOperationalChanges,
    loadOperationalSettings,
    saveOperationalSettings,
  }
}
