<template>
  <section class="rule-authoring">
    <div class="rule-authoring__header">
      <div>
        <div class="rule-authoring__title">AI 数据规则助手</div>
        <div class="rule-authoring__hint">
          自然语言会被解析成封闭规则，再经过服务端编译、隔离测试和发布门禁。
        </div>
      </div>
      <v-chip :color="schemaContextReady ? 'success' : 'warning'" outlined small>
        {{ schemaContextReady ? 'Schema 上下文已固定' : '请先选择 Schema 上下文' }}
      </v-chip>
    </div>

    <div class="rule-authoring__context mt-4">
      <div>
        <span>输入</span>
        <strong>{{ contextLabel('input') }}</strong>
      </div>
      <v-icon small color="primary">mdi-arrow-right</v-icon>
      <div>
        <span>输出</span>
        <strong>{{ contextLabel('output') }}</strong>
      </div>
      <v-btn
        v-if="!schemaContextReady"
        class="ml-auto"
        text
        small
        color="primary"
        @click="$emit('request-context')"
      >
        选择上下文
      </v-btn>
    </div>

    <v-textarea
      v-model="sourceText"
      class="mt-4"
      outlined
      dense
      hide-details
      rows="4"
      :placeholder="placeholder"
      aria-label="自然语言数据规则"
    />

    <div class="d-flex justify-end mt-3">
      <v-btn
        color="primary"
        depressed
        :loading="loading"
        :disabled="!sourceText.trim() || !schemaContextReady"
        @click="interpret"
      >
        <v-icon left small>mdi-auto-fix</v-icon>
        解析约束
      </v-btn>
    </div>

    <v-alert
      v-if="result && result.status === 'clarification_required'"
      class="mt-4 mb-0"
      type="warning"
      text
      dense
    >
      <strong>需要补充约束</strong>
      <ul v-if="ambiguities.length" class="mt-2 mb-0">
        <li v-for="item in ambiguities" :key="item">{{ item }}</li>
      </ul>
    </v-alert>

    <div v-if="candidate" class="rule-authoring__candidate mt-4">
      <div class="d-flex align-center justify-space-between">
        <div>
          <strong>{{ candidateTitle }}</strong>
          <div class="rule-authoring__hint">{{ candidate.explanation }}</div>
        </div>
        <v-chip small color="primary" outlined>
          置信度 {{ Math.round(Number(candidate.confidence || 0) * 100) }}%
        </v-chip>
      </div>

      <div class="rule-authoring__summary mt-3">
        <div>
          <span class="rule-authoring__eyebrow">规则名称</span>
          <strong>{{ governedName }}</strong>
        </div>
        <div>
          <span class="rule-authoring__eyebrow">处理步骤</span>
          <strong>{{ governedStepCount }} 个封闭操作</strong>
        </div>
        <div>
          <span class="rule-authoring__eyebrow">生成凭据</span>
          <strong>{{ result.generation_receipt ? '已签发' : '不适用' }}</strong>
        </div>
      </div>

      <v-alert v-if="assumptions.length" class="mt-3 mb-0" type="info" text dense>
        <strong>AI 假设</strong>
        <div v-for="item in assumptions" :key="item">· {{ item }}</div>
      </v-alert>
      <v-alert v-if="ambiguities.length" class="mt-3 mb-0" type="warning" text dense>
        <strong>仍需人工确认的歧义</strong>
        <div v-for="item in ambiguities" :key="item">· {{ item }}</div>
      </v-alert>

      <div class="rule-authoring__provenance mt-3">
        <v-icon small color="primary">mdi-shield-check</v-icon>
        <span class="ml-2">
          {{ modelProvenance }}
        </span>
      </div>

      <div class="d-flex align-center mt-4">
        <v-btn
          small
          color="primary"
          outlined
          :disabled="candidateAccepted"
          @click="acceptCandidate"
        >
          采用候选
        </v-btn>
        <v-btn
          v-if="candidateAccepted && !versionAsset"
          class="ml-3"
          small
          color="primary"
          :loading="versionLoading"
          :disabled="!canEdit"
          @click="createGovernedVersion"
        >
          创建草稿版本
        </v-btn>
      </div>
    </div>

    <div v-if="versionAsset" class="rule-authoring__lifecycle mt-4">
      <div class="d-flex align-center">
        <strong>受治理版本 V{{ versionAsset.version_no || 1 }}</strong>
        <v-chip class="ml-2" small outlined>{{ versionAsset.status }}</v-chip>
        <span class="rule-authoring__version-id ml-3">{{ versionAsset.id }}</span>
      </div>
      <div class="d-flex flex-wrap mt-3">
        <v-btn
          small
          color="primary"
          :loading="validateLoading"
          :disabled="!canEdit || versionAsset.status !== 'draft'"
          @click="validateVersion"
        >
          1. 编译验证
        </v-btn>
        <v-btn
          class="ml-2"
          small
          color="primary"
          :loading="testLoading"
          :disabled="!canEdit || !logicalPlanId || versionAsset.status !== 'draft'"
          @click="testVersion"
        >
          2. 隔离样本测试
        </v-btn>
        <v-btn
          class="ml-2"
          small
          color="success"
          :loading="publishLoading"
          :disabled="!canPublish || versionAsset.status !== 'validated'"
          @click="publishVersion"
        >
          3. 发布固定版本
        </v-btn>
      </div>
      <compilation-evidence
        ref="evidence"
        class="mt-4"
        :version-id="versionAsset.id"
        :asset-type="candidate.candidate_type === 'standard' ? 'standard' : 'rule'"
      />
    </div>
  </section>
</template>

<script>
import {
  createRuleVersion,
  createStandardVersion,
  interpretRule,
  publishRuleVersion,
  publishStandardVersion,
  testRuleVersion,
  validateRuleVersion
} from '@/api/dataRules'
import CompilationEvidence from './CompilationEvidence'

export default {
  name: 'RuleAuthoringPanel',
  components: { CompilationEvidence },
  props: {
    authoringSurface: {
      type: String,
      required: true,
      validator: value => ['data_standard', 'data_flow'].includes(value)
    },
    context: {
      type: Object,
      default: () => ({})
    },
    initialText: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      sourceText: this.initialText || '',
      loading: false,
      result: null,
      candidateAccepted: false,
      versionLoading: false,
      validateLoading: false,
      testLoading: false,
      publishLoading: false,
      versionAsset: null,
      logicalPlanId: null
    }
  },
  computed: {
    placeholder () {
      return this.authoringSurface === 'data_standard'
        ? '例如：客户手机号去除首尾空格后必须为 11 位数字，不符合时拒绝入库。'
        : '例如：按 customer_id 去重保留更新时间最新记录，再校验手机号格式。'
    },
    candidate () {
      return this.result?.status === 'ready' ? this.result.candidate : null
    },
    assumptions () {
      return this.candidate?.assumptions || []
    },
    ambiguities () {
      return this.candidate?.ambiguities || []
    },
    candidateTitle () {
      return this.candidate?.candidate_type === 'standard'
        ? '数据标准候选已生成'
        : '可执行规则候选已生成'
    },
    governedName () {
      return this.candidate?.rule_spec?.name || this.candidate?.standard_spec?.name || '未命名候选'
    },
    governedStepCount () {
      if (this.candidate?.rule_spec) return this.candidate.rule_spec.steps?.length || 0
      return this.candidate?.standard_spec?.clauses?.length || 0
    },
    modelProvenance () {
      if (!this.result) return ''
      return [
        this.result.model_provider || 'model-provider',
        this.result.model_name || 'model',
        this.result.prompt_version || 'prompt',
        `repair ${this.result.repair_attempts || 0}`
      ].join(' · ')
    },
    schemaContextReady () {
      const input = this.context.input_schema_snapshot_id ||
        this.context.input_schema_ref ||
        this.context.input ||
        this.context.source_table_ids?.length
      const output = this.context.output_schema_snapshot_id ||
        this.context.output_schema_ref ||
        this.context.output ||
        this.context.target_table_ids?.length
      return Boolean(input && output)
    },
    permissions () {
      return this.$store.getters.userInfo?.permissions || []
    },
    canEdit () {
      return this.permissions.includes('rules:edit')
    },
    canPublish () {
      return this.permissions.includes('rules:publish')
    }
  },
  watch: {
    initialText (value) {
      if (value !== this.sourceText) this.sourceText = value || ''
    }
  },
  methods: {
    contextLabel (direction) {
      const value = direction === 'input'
        ? this.context.input_schema_snapshot_id || this.context.input_schema_ref || this.context.input || this.context.source_table_ids
        : this.context.output_schema_snapshot_id || this.context.output_schema_ref || this.context.output || this.context.target_table_ids
      if (Array.isArray(value)) return value.length ? `${value.length} 个数据集` : '尚未选择'
      return value || '尚未选择'
    },
    async interpret () {
      this.loading = true
      this.result = null
      this.candidateAccepted = false
      this.versionAsset = null
      this.logicalPlanId = null
      try {
        const { data } = await interpretRule({
          source_text: this.sourceText,
          authoring_surface: this.authoringSurface,
          context: this.context
        })
        this.result = data
      } catch (error) {
        this.$snackbar.error(error || '规则解析失败')
      } finally {
        this.loading = false
      }
    },
    acceptCandidate () {
      this.candidateAccepted = true
      this.$emit('candidate', this.candidate, this.sourceText)
      this.$snackbar.success('候选已确认，请创建受治理草稿')
    },
    async createGovernedVersion () {
      this.versionLoading = true
      try {
        const isStandard = this.candidate.candidate_type === 'standard'
        const response = isStandard
          ? await createStandardVersion({
            source_text: this.sourceText,
            standard_spec: this.candidate.standard_spec
          })
          : await createRuleVersion({
            source_text: this.sourceText,
            rule_spec: this.candidate.rule_spec,
            generation_receipt: this.result.generation_receipt,
            category: this.authoringSurface === 'data_standard'
              ? 'standard_clause'
              : 'flow_scoped'
          })
        this.versionAsset = response.data
        this.$emit('version', this.versionAsset)
        this.$snackbar.success('草稿已创建，尚不可进入生产线')
      } catch (error) {
        this.$snackbar.error(error || '版本创建失败')
      } finally {
        this.versionLoading = false
      }
    },
    async validateVersion () {
      if (this.candidate.candidate_type === 'standard') {
        this.versionAsset = { ...this.versionAsset, status: 'validated' }
        return
      }
      this.validateLoading = true
      try {
        const { data } = await validateRuleVersion(this.versionAsset.id)
        this.logicalPlanId = data.plan_id
        this.versionAsset = { ...this.versionAsset, status: data.version_status }
        this.refreshEvidence()
      } catch (error) {
        this.$snackbar.error(error || '编译验证失败')
      } finally {
        this.validateLoading = false
      }
    },
    async testVersion () {
      this.testLoading = true
      try {
        const { data } = await testRuleVersion(this.versionAsset.id, this.logicalPlanId)
        this.versionAsset = { ...this.versionAsset, status: data.version_status }
        this.$emit('version', this.versionAsset)
        this.refreshEvidence()
      } catch (error) {
        this.$snackbar.error(error || '隔离样本测试失败')
      } finally {
        this.testLoading = false
      }
    },
    async publishVersion () {
      this.publishLoading = true
      try {
        const response = this.candidate.candidate_type === 'standard'
          ? await publishStandardVersion(this.versionAsset.id)
          : await publishRuleVersion(this.versionAsset.id)
        this.versionAsset = response.data
        this.$emit('version', this.versionAsset)
        this.refreshEvidence()
        this.$snackbar.success('固定版本已发布，可供数据生产线引用')
      } catch (error) {
        this.$snackbar.error(error || '版本发布失败')
      } finally {
        this.publishLoading = false
      }
    },
    refreshEvidence () {
      this.$nextTick(() => this.$refs.evidence?.load())
    }
  }
}
</script>

<style lang="scss" scoped>
.rule-authoring {
  background: #f8fbff;
  border: 1px solid #dbe4ee;
  border-left: 4px solid #1976d2;
  border-radius: 6px;
  padding: 18px;
}
.rule-authoring__header,
.rule-authoring__context,
.rule-authoring__summary {
  align-items: flex-start;
  display: flex;
  gap: 20px;
  justify-content: space-between;
}
.rule-authoring__title {
  color: #17324d;
  font-size: 16px;
  font-weight: 600;
}
.rule-authoring__hint,
.rule-authoring__eyebrow {
  color: #60758a;
  font-size: 12px;
}
.rule-authoring__context,
.rule-authoring__summary {
  background: #edf4fb;
  border-radius: 4px;
  padding: 10px 14px;
}
.rule-authoring__context > div,
.rule-authoring__summary > div {
  display: flex;
  flex: 1;
  flex-direction: column;
}
.rule-authoring__candidate,
.rule-authoring__lifecycle {
  border-top: 1px solid #dbe4ee;
  padding-top: 14px;
}
.rule-authoring__provenance {
  align-items: center;
  color: #506b82;
  display: flex;
  font-size: 12px;
}
.rule-authoring__version-id {
  color: #60758a;
  font-family: monospace;
  font-size: 11px;
  overflow: hidden;
  text-overflow: ellipsis;
}
</style>
