<template>
  <scroll-view class="panel-scroll" scroll-y>
    <view class="toolbar">
      <button
        v-if="!recording"
        class="btn-round"
        type="primary"
        :disabled="!recorderSupported"
        @click="startRecord"
      >
        开始录音
      </button>
      <button v-else class="btn-round btn-stop" type="warn" @click="stopRecord">结束录音</button>
      <text v-if="!recorderSupported" class="hint">当前环境不支持录音，请使用微信小程序或 App</text>
      <text v-else-if="recording" class="hint recording">正在录音…</text>
    </view>

    <view class="section-title">录音列表</view>
    <view v-if="!recordings.length" class="empty">暂无录音，点击「开始录音」记录相处时刻</view>
    <view v-for="item in recordings" :key="item.id" class="rec-card">
      <view class="rec-head">
        <text class="rec-time">{{ formatDate(item.createdAt) }}</text>
        <text class="rec-dur">{{ formatDuration(item.duration) }}</text>
      </view>
      <view class="rec-actions">
        <button class="btn-mini" size="mini" @click="play(item)" :disabled="!item.tempFilePath">试听</button>
        <button
          class="btn-mini primary"
          size="mini"
          :disabled="item.analyzing"
          @click="analyze(item)"
        >
          {{ item.analyzing ? '分析中…' : item.analysisText ? '重新分析' : '分析录音' }}
        </button>
      </view>
      <text v-if="item.analysisText" class="rec-preview">{{ truncate(item.analysisText, 80) }}</text>
    </view>
  </scroll-view>
</template>

<script>
const KEY = 'xixi_recordings';

export default {
  name: 'XixiRecord',
  data() {
    return {
      recordings: [],
      recording: false,
      recorderSupported: false,
      recorderManager: null,
      innerAudio: null,
    };
  },
  mounted() {
    this.recorderSupported = typeof uni.getRecorderManager === 'function';
    this.loadList();
    if (this.recorderSupported) {
      this.recorderManager = uni.getRecorderManager();
      this.recorderManager.onStop((res) => {
        this.recording = false;
        const duration = res.duration || 0;
        const tempFilePath = res.tempFilePath || '';
        if (!tempFilePath) {
          uni.showToast({ title: '未获取到录音文件', icon: 'none' });
          return;
        }
        const item = {
          id: `r_${Date.now()}`,
          tempFilePath,
          duration,
          createdAt: Date.now(),
          analysisText: '',
          analyzing: false,
        };
        this.recordings.unshift(item);
        this.persist();
        uni.showToast({ title: '已保存录音', icon: 'success' });
        this.$emit('recordings-changed');
      });
      this.recorderManager.onError(() => {
        this.recording = false;
        uni.showToast({ title: '录音出错', icon: 'none' });
      });
    }
  },
  beforeUnmount() {
    this.stopAudio();
  },
  methods: {
    loadList() {
      try {
        const list = uni.getStorageSync(KEY);
        this.recordings = Array.isArray(list) ? list : [];
      } catch (e) {
        this.recordings = [];
      }
    },
    persist() {
      try {
        uni.setStorageSync(KEY, this.recordings);
      } catch (e) {
        /* ignore */
      }
    },
    startRecord() {
      if (!this.recorderSupported || !this.recorderManager) return;
      this.recording = true;
      try {
        this.recorderManager.start({
          duration: 600000,
          sampleRate: 44100,
          numberOfChannels: 1,
          encodeBitRate: 96000,
          format: 'mp3',
        });
      } catch (e) {
        this.recording = false;
        uni.showToast({ title: '无法开始录音', icon: 'none' });
      }
    },
    stopRecord() {
      if (this.recorderManager && this.recording) {
        this.recorderManager.stop();
      }
    },
    play(item) {
      if (!item.tempFilePath) return;
      this.stopAudio();
      const ctx = uni.createInnerAudioContext();
      this.innerAudio = ctx;
      ctx.src = item.tempFilePath;
      ctx.onEnded(() => this.stopAudio());
      ctx.onError(() => {
        uni.showToast({ title: '播放失败', icon: 'none' });
        this.stopAudio();
      });
      ctx.play();
    },
    stopAudio() {
      if (this.innerAudio) {
        try {
          this.innerAudio.stop();
          this.innerAudio.destroy();
        } catch (e) {
          /* ignore */
        }
        this.innerAudio = null;
      }
    },
    analyze(item) {
      const idx = this.recordings.findIndex((r) => r.id === item.id);
      if (idx < 0) return;
      const cur = this.recordings[idx];
      this.recordings.splice(idx, 1, { ...cur, analyzing: true });
      const who = uni.getStorageSync('xixi_who_am_i') || {};
      const meet = uni.getStorageSync('xixi_first_meeting') || {};
      const id = item.id;
      setTimeout(() => {
        const i = this.recordings.findIndex((r) => r.id === id);
        if (i < 0) return;
        const row = this.recordings[i];
        const sec = Math.max(1, Math.round((row.duration || 0) / 1000));
        const text = this.buildMockAnalysis(sec, who, meet);
        this.recordings.splice(i, 1, { ...row, analysisText: text, analyzing: false });
        this.persist();
        uni.showToast({ title: '分析完成', icon: 'success' });
        this.$emit('recordings-changed');
      }, 900);
    },
    buildMockAnalysis(seconds, who, meet) {
      const intro = who.selfIntro ? '你已填写「我是谁」，建议在真实对话中自然带出其中 1～2 点，避免像背稿。' : '尚未填写「我是谁」，补全后诊断可结合你的自我描述更贴切。';
      const goal = meet.meetingGoal ? `结合你写的见面目标「${meet.meetingGoal.slice(0, 40)}${meet.meetingGoal.length > 40 ? '…' : ''}」，可回顾本次对话是否朝该方向推进。` : '可补充「本次见面要达到的结果」，便于对照复盘。';
      return (
        `【喜喜 · AI 相处诊断】（示例）\n\n` +
        `· 录音时长约 ${seconds} 秒。\n` +
        `· ${intro}\n` +
        `· ${goal}\n\n` +
        `沟通氛围：语气平稳、留白适中更易建立信任；若语速偏快，可适当停顿给对方回应空间。\n` +
        `下一步：在「诊断结果」页查看完整记录；接入语音转写与大模型后，将替换为基于真实内容的分析。`
      );
    },
    formatDate(ts) {
      const d = new Date(ts);
      const p = (n) => (n < 10 ? '0' + n : '' + n);
      return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
    },
    formatDuration(ms) {
      const s = Math.round((ms || 0) / 1000);
      const m = Math.floor(s / 60);
      const r = s % 60;
      return m > 0 ? `${m}分${r}秒` : `${r}秒`;
    },
    truncate(s, n) {
      if (!s) return '';
      return s.length <= n ? s : s.slice(0, n) + '…';
    },
  },
};
</script>

<style scoped>
.panel-scroll {
  height: 100%;
  box-sizing: border-box;
  padding: 24rpx 28rpx 32rpx;
}
.toolbar {
  margin-bottom: 24rpx;
}
.btn-round {
  border-radius: 999rpx;
  background: linear-gradient(135deg, #ff6b9d, #e91e8c);
  border: none;
  margin-bottom: 12rpx;
}
.btn-stop {
  background: linear-gradient(135deg, #ff8a65, #f4511e);
}
.hint {
  display: block;
  font-size: 24rpx;
  color: #888;
  margin-top: 8rpx;
}
.hint.recording {
  color: #e91e8c;
  font-weight: 600;
}
.section-title {
  font-size: 30rpx;
  font-weight: 600;
  color: #333;
  margin-bottom: 16rpx;
}
.empty {
  font-size: 26rpx;
  color: #999;
  padding: 40rpx 0;
  text-align: center;
}
.rec-card {
  background: #fff;
  border-radius: 20rpx;
  padding: 24rpx;
  margin-bottom: 20rpx;
  box-shadow: 0 4rpx 24rpx rgba(233, 30, 140, 0.06);
}
.rec-head {
  display: flex;
  justify-content: space-between;
  margin-bottom: 16rpx;
}
.rec-time {
  font-size: 26rpx;
  color: #333;
}
.rec-dur {
  font-size: 24rpx;
  color: #e91e8c;
}
.rec-actions {
  display: flex;
  gap: 20rpx;
}
.btn-mini.primary {
  background: #fff0f5;
  color: #e91e8c;
  border: 1rpx solid #ffb6c1;
}
.rec-preview {
  display: block;
  margin-top: 16rpx;
  font-size: 24rpx;
  color: #666;
  line-height: 1.5;
}
</style>
