<template>
  <div class="p-2 public-opinion-page">
    <!-- 标题区 -->
    <div class="public-opinion-header">
      <h2 class="page-title">舆情推送</h2>
      <div class="page-subtitle">实时监测舆情信息,及时推送预警</div>
    </div>

    <!-- ① 数据卡片 -->
    <el-row :gutter="20" class="mb-2">
      <el-col :span="6">
        <el-card shadow="hover" class="stat-card">
          <div class="stat-card-content">
            <div class="stat-info">
              <div class="stat-title">今日舆情总数</div>
              <div class="stat-value">{{ stats.todayTotal || 0 }}</div>
              <div class="stat-extra stat-extra-up" v-if="stats.todayGrowth !== undefined">
                <el-icon v-if="stats.todayGrowth >= 0"><CaretTop /></el-icon>
                <el-icon v-else><CaretBottom /></el-icon>
                <span>{{ Math.abs(stats.todayGrowth) }}% 较昨日</span>
              </div>
            </div>
            <div class="stat-icon stat-icon-blue">
              <el-icon><ChatLineSquare /></el-icon>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card shadow="hover" class="stat-card">
          <div class="stat-card-content">
            <div class="stat-info">
              <div class="stat-title">重大舆情</div>
              <div class="stat-value">{{ stats.majorTotal || 0 }}</div>
              <div class="stat-extra" :class="(stats.majorChange || 0) >= 0 ? 'stat-extra-up' : 'stat-extra-down'">
                <el-icon v-if="(stats.majorChange || 0) >= 0"><CaretTop /></el-icon>
                <el-icon v-else><CaretBottom /></el-icon>
                <span>{{ Math.abs(stats.majorChange || 0) }} 较昨日</span>
              </div>
            </div>
            <div class="stat-icon stat-icon-red">
              <el-icon><Warning /></el-icon>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card shadow="hover" class="stat-card">
          <div class="stat-card-content">
            <div class="stat-info">
              <div class="stat-title">已处理舆情</div>
              <div class="stat-value">{{ stats.handledTotal || 0 }}</div>
              <div class="stat-extra stat-extra-up">
                <span>{{ stats.handleRate || 0 }}% 处理率</span>
              </div>
            </div>
            <div class="stat-icon stat-icon-green">
              <el-icon><CircleCheck /></el-icon>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card shadow="hover" class="stat-card">
          <div class="stat-card-content">
            <div class="stat-info">
              <div class="stat-title">待处理舆情</div>
              <div class="stat-value">{{ stats.pendingTotal || 0 }}</div>
              <div class="stat-extra stat-extra-warning">
                <span>需要紧急处理</span>
              </div>
            </div>
            <div class="stat-icon stat-icon-orange">
              <el-icon><Bell /></el-icon>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- ② 近七天舆情趋势 -->
    <el-card shadow="hover" class="mb-2">
      <template #header>
        <span class="section-title">近7天舆情趋势</span>
      </template>
      <div ref="trendChartRef" class="trend-chart"></div>
    </el-card>

    <!-- ③ 重大舆情明细 -->
    <el-card shadow="hover">
      <template #header>
        <div class="section-header">
          <span class="section-title">重大舆情明细</span>
          <el-button type="primary" :icon="Plus" @click="handleAdd">新增舆情</el-button>
        </div>
      </template>

      <el-table v-loading="loading" :data="majorList" border stripe>
        <el-table-column label="舆情标题" align="center" prop="opinionTitle" :show-overflow-tooltip="true" min-width="220" />
        <el-table-column label="来源" align="center" prop="source" width="160" :show-overflow-tooltip="true" />
        <el-table-column label="发布时间" align="center" prop="publishTime" width="180" />
        <el-table-column label="风险等级" align="center" prop="riskLevel" width="100">
          <template #default="scope">
            <el-tag :type="getRiskLevelTag(scope.row.riskLevel)">{{ scope.row.riskLevel }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="状态" align="center" prop="status" width="100">
          <template #default="scope">
            <el-tag :type="getStatusTag(scope.row.status)">{{ scope.row.status || '待处理' }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" fixed="right" align="center" width="120" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-button link type="primary" @click="handleProcess(scope.row)">处理</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- ④ 新增舆情对话框 -->
    <el-dialog v-model="dialog.visible" title="新增舆情信息" width="640px" append-to-body @close="closeAddDialog">
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
        <el-form-item label="舆情标题" prop="opinionTitle">
          <el-input v-model="form.opinionTitle" placeholder="请输入舆情内容标题" maxlength="200" show-word-limit />
        </el-form-item>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="舆情来源" prop="source">
              <el-select v-model="form.source" placeholder="请选择舆情来源" style="width: 100%">
                <el-option
                  v-for="dict in opinion_source_dict"
                  :key="dict.value"
                  :label="dict.label"
                  :value="dict.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="发布时间" prop="publishTime">
              <el-date-picker
                v-model="form.publishTime"
                type="datetime"
                placeholder="请选择发布时间"
                value-format="YYYY-MM-DD HH:mm:ss"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="风险等级" prop="riskLevel">
              <el-select v-model="form.riskLevel" placeholder="请选择风险等级" style="width: 100%">
                <el-option
                  v-for="dict in risk_opinion_level_dict"
                  :key="dict.value"
                  :label="dict.label"
                  :value="dict.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="负责人" prop="responsiblePerson">
              <el-input v-model="form.responsiblePerson" placeholder="请输入负责人" maxlength="50" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="舆情链接" prop="opinionLink">
          <el-input v-model="form.opinionLink" placeholder="请输入舆情外部链接(URL)" maxlength="500" />
        </el-form-item>
        <el-form-item label="舆情内容" prop="opinionContent">
          <el-input
            v-model="form.opinionContent"
            type="textarea"
            :rows="4"
            placeholder="请输入舆情内容"
            maxlength="2000"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="处置建议" prop="disposalSuggestion">
          <el-input
            v-model="form.disposalSuggestion"
            type="textarea"
            :rows="3"
            placeholder="请输入舆情处置建议"
            maxlength="1000"
            show-word-limit
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="cancelAdd">取 消</el-button>
          <el-button type="primary" @click="submitForm">提 交</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 处理舆情弹窗 -->
    <el-dialog v-model="processDialog.visible" title="处理舆情" width="520px" append-to-body>
      <el-form ref="processFormRef" :model="processForm" :rules="processRules" label-width="100px">
        <el-form-item label="舆情标题">
          <span class="readonly-text">{{ processForm.opinionTitle }}</span>
        </el-form-item>
        <el-form-item label="来源">
          <span class="readonly-text">{{ processForm.source }}</span>
        </el-form-item>
        <el-form-item label="风险等级">
          <el-tag :type="getRiskLevelTag(processForm.riskLevel)">{{ processForm.riskLevel }}</el-tag>
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-select v-model="processForm.status" placeholder="请选择状态" style="width: 100%">
            <el-option
              v-for="dict in risk_opinion_status_dict"
              :key="dict.value"
              :label="dict.label"
              :value="dict.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="处理结果" prop="handleResult">
          <el-input
            v-model="processForm.handleResult"
            type="textarea"
            :rows="4"
            placeholder="请录入处理结果"
            maxlength="1000"
            show-word-limit
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="processDialog.visible = false">取 消</el-button>
          <el-button type="primary" @click="submitProcessForm">提 交</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="PublicOpinion" lang="ts">
import { ref, reactive, toRefs, onMounted, onBeforeUnmount, getCurrentInstance, nextTick } from 'vue';
import * as echarts from 'echarts';
import {
  addPublicOpinion,
  handlePublicOpinion,
  getPublicOpinionStats,
  getPublicOpinionTrend,
  getMajorOpinionList
} from '@/api/risk/publicOpinion';
import type { RiskPublicOpinionBo, RiskPublicOpinionVo, PublicOpinionStatsVo, PublicOpinionTrendVo } from '@/api/risk/types';
import { FormInstance } from 'element-plus';
import type { ComponentInternalInstance } from 'vue';
import { CaretTop, CaretBottom, ChatLineSquare, Warning, CircleCheck, Bell, Plus } from '@element-plus/icons-vue';

const { proxy } = getCurrentInstance() as ComponentInternalInstance;

// ============ 状态 ============
const majorList = ref<RiskPublicOpinionVo[]>([]);
const loading = ref(false);

const stats = ref<PublicOpinionStatsVo>({
  todayTotal: 0,
  yesterdayTotal: 0,
  todayGrowth: 0,
  majorTotal: 0,
  majorYesterday: 0,
  majorChange: 0,
  handledTotal: 0,
  handleBase: 0,
  handleRate: 0,
  pendingTotal: 0
});

const trendList = ref<PublicOpinionTrendVo[]>([]);

// 字典
const { opinion_source: opinion_source_dict, risk_opinion_level: risk_opinion_level_dict, risk_opinion_status: risk_opinion_status_dict } = toRefs<any>(
  proxy?.useDict('opinion_source', 'risk_opinion_level', 'risk_opinion_status')
);

// 图表
const trendChartRef = ref<HTMLElement>();
let trendChart: echarts.ECharts | null = null;

// 表单
const formRef = ref<FormInstance>();
const processFormRef = ref<FormInstance>();

const data = reactive<any>({
  form: {
    id: undefined,
    opinionTitle: '',
    source: '',
    publishTime: '',
    riskLevel: '',
    responsiblePerson: '',
    opinionLink: '',
    opinionContent: '',
    disposalSuggestion: '',
    status: '待处理'
  } as RiskPublicOpinionBo,
  rules: {
    opinionTitle: [{ required: true, message: '舆情标题不能为空', trigger: 'blur' }],
    source: [{ required: true, message: '请选择舆情来源', trigger: 'change' }],
    publishTime: [{ required: true, message: '请选择发布时间', trigger: 'change' }],
    riskLevel: [{ required: true, message: '请选择风险等级', trigger: 'change' }],
    opinionContent: [{ required: true, message: '请输入舆情内容', trigger: 'blur' }]
  }
});

const { form, rules } = toRefs(data);

const dialog = reactive({ visible: false });
const processDialog = reactive({ visible: false });
const processForm = reactive<any>({
  id: undefined,
  opinionTitle: '',
  source: '',
  riskLevel: '',
  status: '处理中',
  handleResult: ''
});

const processRules = {
  status: [{ required: true, message: '请选择状态', trigger: 'change' }],
  handleResult: [{ required: true, message: '请录入处理结果', trigger: 'blur' }]
};

// ============ 数据加载 ============
const loadStats = async () => {
  const res = await getPublicOpinionStats();
  if (res.data) {
    stats.value = res.data;
  }
};

const loadTrend = async () => {
  const res = await getPublicOpinionTrend();
  trendList.value = res.data || [];
  await nextTick();
  renderTrendChart();
};

const loadMajorList = async () => {
  loading.value = true;
  try {
    const res = await getMajorOpinionList();
    majorList.value = res.data || [];
  } finally {
    loading.value = false;
  }
};

const loadAll = async () => {
  await Promise.all([loadStats(), loadTrend(), loadMajorList()]);
};

// ============ 图表渲染 ============
const renderTrendChart = () => {
  if (!trendChartRef.value) return;
  if (!trendChart) {
    trendChart = echarts.init(trendChartRef.value);
  }
  const dates = trendList.value.map((it) => it.date?.slice(5) || '');
  const totalArr = trendList.value.map((it) => it.totalCount || 0);
  const majorArr = trendList.value.map((it) => it.majorCount || 0);
  const handledArr = trendList.value.map((it) => it.handledCount || 0);

  trendChart.setOption({
    tooltip: { trigger: 'axis' },
    legend: {
      data: ['总舆情', '重大舆情', '已处理'],
      top: 0,
      icon: 'circle'
    },
    grid: { left: 40, right: 30, top: 40, bottom: 30 },
    xAxis: {
      type: 'category',
      data: dates,
      boundaryGap: false,
      axisLine: { lineStyle: { color: '#e0e0e0' } },
      axisLabel: { color: '#666' }
    },
    yAxis: {
      type: 'value',
      minInterval: 1,
      splitLine: { lineStyle: { type: 'dashed', color: '#eee' } },
      axisLabel: { color: '#666' }
    },
    series: [
      {
        name: '总舆情',
        type: 'line',
        smooth: true,
        symbol: 'circle',
        symbolSize: 6,
        data: totalArr,
        itemStyle: { color: '#409EFF' },
        lineStyle: { width: 2, color: '#409EFF' }
      },
      {
        name: '重大舆情',
        type: 'line',
        smooth: true,
        symbol: 'circle',
        symbolSize: 6,
        data: majorArr,
        itemStyle: { color: '#F56C6C' },
        lineStyle: { width: 2, color: '#F56C6C' }
      },
      {
        name: '已处理',
        type: 'line',
        smooth: true,
        symbol: 'circle',
        symbolSize: 6,
        data: handledArr,
        itemStyle: { color: '#67C23A' },
        lineStyle: { width: 2, color: '#67C23A' }
      }
    ]
  });
};

const handleResize = () => {
  trendChart?.resize();
};

// ============ 操作 ============
const handleAdd = () => {
  resetForm();
  dialog.visible = true;
};

const submitForm = () => {
  formRef.value?.validate(async (valid: boolean) => {
    if (!valid) return;
    await addPublicOpinion(form.value);
    proxy?.$modal.msgSuccess('新增成功');
    dialog.visible = false;
    await loadAll();
  });
};

const cancelAdd = () => {
  dialog.visible = false;
  resetForm();
};

const closeAddDialog = () => {
  dialog.visible = false;
  resetForm();
};

const resetForm = () => {
  form.value = {
    id: undefined,
    opinionTitle: '',
    source: '',
    publishTime: '',
    riskLevel: '',
    responsiblePerson: '',
    opinionLink: '',
    opinionContent: '',
    disposalSuggestion: '',
    status: '待处理'
  } as RiskPublicOpinionBo;
  formRef.value?.resetFields();
};

const handleProcess = (row: RiskPublicOpinionVo) => {
  processForm.id = row.id;
  processForm.opinionTitle = row.opinionTitle;
  processForm.source = row.source;
  processForm.riskLevel = row.riskLevel;
  processForm.status = row.status && row.status !== '已处理' ? row.status : '处理中';
  processForm.handleResult = row.handleResult || '';
  processDialog.visible = true;
};

const submitProcessForm = () => {
  processFormRef.value?.validate(async (valid: boolean) => {
    if (!valid) return;
    await handlePublicOpinion(processForm.id, { ...processForm });
    proxy?.$modal.msgSuccess('处理成功');
    processDialog.visible = false;
    await loadAll();
  });
};

// ============ 工具 ============
const getRiskLevelTag = (level: string): 'primary' | 'success' | 'warning' | 'info' | 'danger' => {
  const map: Record<string, 'primary' | 'success' | 'warning' | 'info' | 'danger'> = {
    重大: 'danger',
    较大: 'warning',
    一般: 'success',
    高: 'danger',
    中: 'warning',
    低: 'success'
  };
  return map[level] || 'info';
};

const getStatusTag = (status: string): 'primary' | 'success' | 'warning' | 'info' | 'danger' => {
  const map: Record<string, 'primary' | 'success' | 'warning' | 'info' | 'danger'> = {
    待处理: 'danger',
    处理中: 'warning',
    已处理: 'success'
  };
  return map[status] || 'info';
};

// ============ 生命周期 ============
onMounted(async () => {
  await loadAll();
  window.addEventListener('resize', handleResize);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize);
  trendChart?.dispose();
  trendChart = null;
});
</script>

<style scoped lang="scss">
.public-opinion-page {
  padding: 16px;
  height: 100%;
  overflow-y: auto;
  box-sizing: border-box;
}
.public-opinion-header {
  margin-bottom: 16px;
  .page-title {
    font-size: 20px;
    font-weight: 600;
    color: #303133;
    margin: 0 0 4px 0;
  }
  .page-subtitle {
    font-size: 13px;
    color: #909399;
  }
}

.mb-2 { margin-bottom: 16px; }

.stat-card {
  border-radius: 8px;
  :deep(.el-card__body) { padding: 20px; }
}
.stat-card-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.stat-info { flex: 1; }
.stat-title {
  font-size: 13px;
  color: #909399;
  margin-bottom: 8px;
  white-space: nowrap;
}
.stat-value {
  font-size: 28px;
  font-weight: 700;
  color: #303133;
  line-height: 1.2;
  margin-bottom: 8px;
}
.stat-extra {
  font-size: 12px;
  color: #909399;
  display: flex;
  align-items: center;
  gap: 2px;
}
.stat-extra-up { color: #f56c6c; }
.stat-extra-down { color: #67c23a; }
.stat-extra-warning {
  color: #e6a23c;
  font-weight: 600;
}
.stat-icon {
  width: 48px;
  height: 48px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  color: #fff;
}
.stat-icon-blue { background: #ecf5ff; color: #409EFF; }
.stat-icon-red { background: #fef0f0; color: #F56C6C; }
.stat-icon-green { background: #f0f9eb; color: #67C23A; }
.stat-icon-orange { background: #fdf6ec; color: #E6A23C; }

.section-title { font-size: 16px; font-weight: 600; color: #303133; }
.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.trend-chart { width: 100%; height: 360px; }

.readonly-text {
  color: #606266;
  font-size: 14px;
}
</style>
