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

function readCurrentWebEndpoint(initialState) {
  if (typeof window === 'undefined') {
    return {
      host: initialState?.web?.host || '0.0.0.0',
      port: Number(initialState?.web?.port || 5273)
    }
  }

  const fallbackPort = Number(initialState?.web?.port || 5273)
  const port = Number(window.location.port || fallbackPort)

  return {
    host: window.location.hostname || initialState?.web?.host || '0.0.0.0',
    port: Number.isInteger(port) && port > 0 ? port : fallbackPort
  }
}

function shouldExposeServerHost() {
  if (typeof window === 'undefined') {
    return false
  }

  const host = String(window.location.hostname || '').toLowerCase()
  return Boolean(host && host !== '127.0.0.1' && host !== 'localhost' && host !== '::1')
}

function resolveInitialServerHost(initialState) {
  const host = String(initialState?.server?.host || '0.0.0.0').trim()
  const normalized = host.toLowerCase()

  if (shouldExposeServerHost() && (normalized === '127.0.0.1' || normalized === 'localhost' || normalized === '::1')) {
    return '0.0.0.0'
  }

  return host || '0.0.0.0'
}

function createForm(initialState) {
  const currentWeb = readCurrentWebEndpoint(initialState)

  return {
    company_name: initialState?.company?.name || '',
    company_code: initialState?.company?.code || '',
    admin_email: initialState?.company?.admin_email || '',
    admin_username: '',
    admin_password: '',
    admin_password_confirm: '',
    web_host: currentWeb.host,
    web_port: currentWeb.port,
    server_host: resolveInitialServerHost(initialState),
    server_port: initialState?.server?.port || 8000,
    postgres_host: initialState?.database?.host || '127.0.0.1',
    postgres_port: initialState?.database?.port || 5432,
    postgres_db: initialState?.database?.name || 'x_financial',
    postgres_user: initialState?.database?.username || 'postgres',
    postgres_password: '',
    redis_url: initialState?.redis?.url || ''
  }
}

function buildPayload(form) {
  const currentWeb = readCurrentWebEndpoint({
    web: {
      host: form.web_host,
      port: form.web_port
    }
  })

  return {
    company_name: form.company_name.trim(),
    company_code: form.company_code.trim(),
    admin_email: form.admin_email.trim(),
    admin_username: form.admin_username.trim(),
    admin_password: String(form.admin_password || ''),
    admin_password_confirm: String(form.admin_password_confirm || ''),
    web_host: currentWeb.host,
    web_port: currentWeb.port,
    server_host: shouldExposeServerHost() && ['127.0.0.1', 'localhost', '::1'].includes(form.server_host.trim().toLowerCase())
      ? '0.0.0.0'
      : form.server_host.trim(),
    server_port: Number(form.server_port),
    postgres_host: form.postgres_host.trim(),
    postgres_port: Number(form.postgres_port),
    postgres_db: form.postgres_db.trim(),
    postgres_user: form.postgres_user.trim(),
    postgres_password: String(form.postgres_password || ''),
    redis_url: form.redis_url.trim()
  }
}

function buildRuntimeFingerprint(form) {
  return JSON.stringify({
    server_host: form.server_host.trim(),
    server_port: String(form.server_port).trim()
  })
}

function buildDatabaseFingerprint(form) {
  return JSON.stringify({
    postgres_host: form.postgres_host.trim(),
    postgres_port: String(form.postgres_port).trim(),
    postgres_db: form.postgres_db.trim(),
    postgres_user: form.postgres_user.trim(),
    postgres_password: String(form.postgres_password || ''),
    redis_url: form.redis_url.trim()
  })
}

function isEmail(value) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/u.test(String(value || '').trim())
}

export function useSetupView(props, emit) {
  const form = reactive(createForm(props.initialState))
  const activeSection = ref('company')
  let syncingFromProps = false

  watch(
    () => props.initialState,
    (state) => {
      syncingFromProps = true
      Object.assign(form, createForm(state))
      queueMicrotask(() => {
        syncingFromProps = false
      })
    },
    { deep: true }
  )

  watch(
    () => buildRuntimeFingerprint(form),
    (_value, oldValue) => {
      if (oldValue !== undefined && !syncingFromProps) {
        emit('runtime-dirty')
      }
    }
  )

  watch(
    () => buildDatabaseFingerprint(form),
    (_value, oldValue) => {
      if (oldValue !== undefined && !syncingFromProps) {
        emit('database-dirty')
      }
    }
  )

  const companyReady = computed(() => form.company_name.trim().length >= 2)
  const adminReady = computed(() => {
    return Boolean(
      isEmail(form.admin_email) &&
        form.admin_username.trim().length >= 4 &&
        String(form.admin_password || '').length >= 5 &&
        form.admin_password === form.admin_password_confirm
    )
  })
  const runtimeInputsReady = computed(() => {
    return Boolean(
      form.server_host.trim() &&
        String(form.server_port).trim()
    )
  })
  const databaseInputsReady = computed(() => {
    return Boolean(
      form.postgres_host.trim() &&
        String(form.postgres_port).trim() &&
        form.postgres_db.trim() &&
        form.postgres_user.trim() &&
        String(form.postgres_password || '').length > 0
    )
  })

  const runtimeReady = computed(() => runtimeInputsReady.value && props.runtimeTestPassed)
  const databaseReady = computed(() => databaseInputsReady.value && props.databaseTestPassed)
  const finalReady = computed(() => companyReady.value && adminReady.value && runtimeReady.value && databaseReady.value)

  const sections = computed(() => [
    {
      id: 'company',
      index: '01',
      title: '企业信息',
      desc: '填写企业名称与识别编码。',
      complete: companyReady.value
    },
    {
      id: 'admin',
      index: '02',
      title: '管理员安全',
      desc: '配置管理员邮箱、账号与密码。',
      complete: adminReady.value
    },
    {
      id: 'runtime',
      index: '03',
      title: '运行端口',
      desc: 'Web 端口跟随当前启动实例，只检测后端端口占用。',
      complete: runtimeReady.value
    },
    {
      id: 'database',
      index: '04',
      title: '数据库',
      desc: '检测 PostgreSQL 连接，Redis 暂时可选。',
      complete: databaseReady.value
    }
  ])

  const activeStep = computed(() => sections.value.find((section) => section.id === activeSection.value) || sections.value[0])
  const completionCount = computed(() => sections.value.filter((section) => section.complete).length)

  const runtimeEndpoints = computed(() => [
    {
      label: 'Web 当前访问',
      value: `${form.web_host}:${form.web_port}`
    },
    {
      label: 'Server 待启动',
      value: `${form.server_host}:${form.server_port}`
    }
  ])

  const currentTestMessage = computed(() => {
    if (activeSection.value === 'runtime') {
      return props.runtimeTestMessage
    }

    if (activeSection.value === 'database') {
      return props.databaseTestMessage
    }

    return ''
  })

  const currentTestPassed = computed(() => {
    if (activeSection.value === 'runtime') {
      return props.runtimeTestPassed
    }

    if (activeSection.value === 'database') {
      return props.databaseTestPassed
    }

    return false
  })

  const showTestAction = computed(() => ['runtime', 'database'].includes(activeSection.value))
  const testButtonLabel = computed(() => {
    if (activeSection.value === 'runtime') {
      return props.runtimeTesting ? '检测中...' : '检测端口占用'
    }

    if (activeSection.value === 'database') {
      return props.databaseTesting ? '检测中...' : '检测数据库连接'
    }

    return ''
  })
  const testButtonIcon = computed(() => {
    if ((activeSection.value === 'runtime' && props.runtimeTesting) || (activeSection.value === 'database' && props.databaseTesting)) {
      return 'mdi mdi-loading mdi-spin'
    }

    return activeSection.value === 'runtime' ? 'mdi mdi-server' : 'mdi mdi-database'
  })

  const canRuntimeTest = computed(() => Boolean(runtimeInputsReady.value && !props.submitting && !props.runtimeTesting && !props.databaseTesting))
  const canDatabaseTest = computed(() => Boolean(databaseInputsReady.value && !props.submitting && !props.runtimeTesting && !props.databaseTesting))
  const canTest = computed(() => {
    if (activeSection.value === 'runtime') {
      return canRuntimeTest.value
    }

    if (activeSection.value === 'database') {
      return canDatabaseTest.value
    }

    return false
  })

  const submitHint = computed(() => {
    if (activeSection.value === 'admin') {
      if (!form.admin_email.trim() && !form.admin_username.trim() && !String(form.admin_password || '').length) {
        return ''
      }

      if (!form.admin_email.trim()) {
        return '请填写管理员邮箱。'
      }

      if (!isEmail(form.admin_email)) {
        return '管理员邮箱格式不正确。'
      }

      if (form.admin_username.trim() && form.admin_username.trim().length < 4) {
        return '管理员账号至少 4 位。'
      }

      if (String(form.admin_password || '').length > 0 && String(form.admin_password || '').length < 5) {
        return '管理员密码当前至少 5 位。'
      }

      if (
        String(form.admin_password_confirm || '').length > 0 &&
        form.admin_password !== form.admin_password_confirm
      ) {
        return '两次输入的管理员密码不一致。'
      }
    }

    if (activeSection.value === 'runtime') {
      if (!runtimeInputsReady.value) {
        return '请先填写 Server 的主机和端口。'
      }

      if (!props.runtimeTestPassed) {
        return '请先完成端口占用检测。'
      }
    }

    if (activeSection.value === 'database') {
      if (!databaseInputsReady.value) {
        return '请先填写 PostgreSQL 连接信息。'
      }

      if (!props.databaseTestPassed) {
        return '请先完成数据库连接检测。'
      }
    }

    if (activeSection.value === 'company') {
      return ''
    }

    if (!companyReady.value) {
      return '请先完成企业信息。'
    }

    if (!adminReady.value) {
      return '请先完成管理员安全配置。'
    }

    if (!runtimeReady.value) {
      return '请先完成运行端口检测。'
    }

    if (!databaseReady.value) {
      return '请先完成数据库连接检测。'
    }

    return ''
  })

  function goToSection(id) {
    activeSection.value = id
  }

  function submitForm() {
    if (!finalReady.value || props.submitting) {
      return
    }

    emit('submit', buildPayload(form))
  }

  function testSetup() {
    if (!canTest.value) {
      return
    }

    const payload = buildPayload(form)

    if (activeSection.value === 'runtime') {
      emit('runtime-test', payload)
      return
    }

    if (activeSection.value === 'database') {
      emit('database-test', payload)
    }
  }

  return {
    activeSection,
    activeStep,
    canSubmit: finalReady,
    canTest,
    completionCount,
    currentTestMessage,
    currentTestPassed,
    form,
    goToSection,
    runtimeEndpoints,
    sections,
    showTestAction,
    submitForm,
    submitHint,
    testButtonIcon,
    testButtonLabel,
    testSetup
  }
}
