<script lang="ts" setup>
import { onMounted, reactive, ref } from 'vue'
import { useRoute } from 'vue-router'
import { Checkbox, Col, Form, Row } from 'ant-design-vue'

import { useFormValid, useLoginState } from './useLogin'
import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'

import { useDesign } from '@/hooks/web/useDesign'
import { authorize, getAuthorize } from '@/api/base/login'

const FormItem = Form.Item

const { t } = useI18n()
const { query } = useRoute()
const { notification, createErrorModal } = useMessage()
const { prefixCls } = useDesign('login')

const { handleBackLogin } = useLoginState()

const formRef = ref()
const loading = ref(false)

const loginForm = reactive({
  scopes: [] as any[], // 已选中的 scope 数组
})

// URL 上的 client_id、scope 等参数
const params = reactive({
  responseType: undefined as any,
  clientId: undefined as any,
  redirectUri: undefined as any,
  state: undefined as any,
  scopes: [] as any[], // 优先从 query 参数获取；如果未传递，从后端获取
})

// 客户端信息
let client = reactive({
  name: '',
  logo: '',
})

const { validForm } = useFormValid(formRef)

async function init() {
  // 解析参数
  // 例如说【自动授权不通过】：client_id=default&redirect_uri=https%3A%2F%2Fwww.iocoder.cn&response_type=code&scope=user.read%20user.write
  // 例如说【自动授权通过】：client_id=default&redirect_uri=https%3A%2F%2Fwww.iocoder.cn&response_type=code&scope=user.read
  params.responseType = query.response_type as any
  params.clientId = query.client_id as any
  params.redirectUri = query.redirect_uri as any
  params.state = query.state as any
  if (query.scope)
    params.scopes = (query.scope as any).split(' ')

  // 如果有 scope 参数，先执行一次自动授权，看看是否之前都授权过了。
  if (params.scopes.length > 0) {
    const res = await doAuthorize(true, params.scopes, [])
    const href = res
    if (!href) {
      console.log('自动授权未通过！')
      return
    }
    location.href = href
  }

  // 获取授权页的基本信息
  const res = await getAuthorize(params.clientId)
  client = res.client
  // 解析 scope
  let scopes
  // 1.1 如果 params.scope 非空，则过滤下返回的 scopes
  if (params.scopes.length > 0) {
    scopes = []
    for (const scope of res.scopes) {
      if (params.scopes.includes(scope.key))
        scopes.push(scope)
    }
    // 1.2 如果 params.scope 为空，则使用返回的 scopes 设置它
  }
  else {
    scopes = res.scopes
    for (const scope of scopes)
      params.scopes.push(scope.key)
  }
  // 生成已选中的 checkedScopes
  for (const scope of scopes) {
    if (scope.value)
      loginForm.scopes.push(scope.key)
  }
}

async function handleAuthorize(approved) {
  const data = await validForm()
  if (!data)
    return
  try {
    loading.value = true
    // 计算 checkedScopes + uncheckedScopes
    let checkedScopes
    let uncheckedScopes
    if (approved) {
      // 同意授权，按照用户的选择
      checkedScopes = loginForm.scopes
      uncheckedScopes = params.scopes.filter(item => !checkedScopes.includes(item))
    }
    else {
      // 拒绝，则都是取消
      checkedScopes = []
      uncheckedScopes = params.scopes
    }
    // 提交授权的请求
    const res = await doAuthorize(false, checkedScopes, uncheckedScopes)
    if (res) {
      const href = res
      if (!href)
        return

      location.href = href
      notification.success({
        message: t('sys.login.loginSuccessTitle'),
        description: `${t('sys.login.loginSuccessDesc')}`,
        duration: 3,
      })
    }
  }
  catch (error) {
    createErrorModal({
      title: t('sys.api.errorTip'),
      content: (error as unknown as Error).message || t('sys.api.networkExceptionMsg'),
      getContainer: () => document.body.querySelector(`.${prefixCls}`) || document.body,
    })
  }
  finally {
    loading.value = false
  }
}
async function doAuthorize(autoApprove, checkedScopes, uncheckedScopes) {
  return await authorize(
    params.responseType,
    params.clientId,
    params.redirectUri,
    params.state,
    autoApprove,
    checkedScopes,
    uncheckedScopes,
  )
}

function formatScope(scope) {
  // 格式化 scope 授权范围，方便用户理解。
  // 这里仅仅是一个 demo，可以考虑录入到字典数据中，例如说字典类型 "system_oauth2_scope"，它的每个 scope 都是一条字典数据。
  switch (scope) {
    case 'user.read':
      return t('sys.login.ssoInfoDesc')
    case 'user.write':
      return t('sys.login.ssoEditDesc')
    default:
      return scope
  }
}

onMounted(() => {
  init()
})
</script>

<template>
  <h2 class="enter-x mb-3 text-center text-2xl font-bold xl:text-left xl:text-3xl">
    {{ client.name + t('sys.login.ssoSignInFormTitle') }}
  </h2>
  <Form ref="formRef" class="enter-x p-4" :model="loginForm" @keypress.enter="handleAuthorize(true)">
    此第三方应用请求获取以下权限：
    <Row class="enter-x">
      <Col :span="12">
        <template v-for="scope in params.scopes" :key="scope">
          <FormItem>
            <!-- No logic, you need to deal with it yourself -->
            <Checkbox :checked="scope" size="small">
              <a-button type="link" size="small">
                {{ formatScope(scope) }}
              </a-button>
            </Checkbox>
          </FormItem>
        </template>
      </Col>
    </Row>

    <FormItem class="enter-x">
      <a-button type="primary" size="large" block :loading="loading" @click="handleAuthorize(true)">
        {{ t('sys.login.loginButton') }}
      </a-button>
      <a-button size="large" class="enter-x mt-4" block @click="handleBackLogin">
        {{ t('common.cancelText') }}
      </a-button>
    </FormItem>
  </Form>
</template>
