const Base = require('./base');
const jwt = require('jsonwebtoken');
const COS = require('cos-nodejs-sdk-v5');
const fs = require('fs');
const path = require('path');
const cosConfig = require('../config/cos.js');

const APP_REMARK = 'pap_mini_cytx';

module.exports = class extends Base {
  // POST /api/mp/login
  async loginAction() {
    const code = this.post('code');
    if (!code) return this.json({ code: 1, msg: '缺少code参数' });
    try {
      const wechatService = this.service('wechat');
      const session = await wechatService.code2Session(code, APP_REMARK);
      const { openid, unionid } = session;
      if (!openid) return this.json({ code: 1, msg: '获取openid失败' });

      const userModel = this.model('wechat_user');
      let user = await userModel.findByOpenId(openid, APP_REMARK);
      if (think.isEmpty(user)) {
        const id = await userModel.createUser({
          open_id: openid, union_id: unionid || '', app_remark: APP_REMARK,
          nickname: '微信用户', status: 1
        });
        user = await userModel.where({ id }).find();
      }
      if (user.status !== 1) return this.json({ code: 1, msg: '账号已被停用' });

      const token = jwt.sign(
        { id: user.id, open_id: user.open_id, type: 'mp' },
        Base.JWT_SECRET, { expiresIn: 7 * 24 * 60 * 60 }
      );
      let patient = null;
      if (user.patient_id) {
        patient = await this.model('patient')
          .field('id, patient_no, name, phone, status, auth_status')
          .where({ id: user.patient_id, is_deleted: 0 }).find();
        if (think.isEmpty(patient)) patient = null;
      }
      return this.json({ code: 0, data: { token, userInfo: {
        id: user.id, nickname: user.nickname || '', avatar: user.avatar || '',
        phone: user.phone || '', patient_id: user.patient_id || null, patient
      }}});
    } catch (error) {
      think.logger.error('login error:', error);
      return this.json({ code: 1, msg: error.message || '登录失败' });
    }
  }

  // POST /api/mp/phoneLogin - H5 手机号验证码登录
  async phoneLoginAction() {
    const { mobile, code } = this.post();
    if (!mobile || !/^1[3-9]\d{9}$/.test(mobile)) {
      return this.json({ code: 1, msg: '请输入正确的手机号' });
    }
    if (!code || !/^\d{6}$/.test(code)) {
      return this.json({ code: 1, msg: '请输入6位验证码' });
    }
    const verifyResult = await this.verifySmsCode(mobile, 'login', code);
    if (!verifyResult.success) return this.json({ code: 1, msg: verifyResult.message });

    try {
      const userModel = this.model('wechat_user');
      // 查找已有的 H5 用户（open_id 以 h5_ 开头）
      let user = await userModel.where({
        open_id: 'h5_' + mobile, app_remark: APP_REMARK, status: 1
      }).find();

      if (think.isEmpty(user)) {
        // 没有 H5 用户记录，创建一条新的
        // 同时查找该手机号是否已有 patient（可能在小程序端已认证）
        let patientId = null;
        const patient = await this.model('patient').where({ phone: mobile, is_deleted: 0 }).find();
        if (!think.isEmpty(patient)) patientId = patient.id;

        const id = await userModel.createUser({
          open_id: 'h5_' + mobile, union_id: '', app_remark: APP_REMARK,
          nickname: '', phone: mobile, patient_id: patientId, status: 1
        });
        user = await userModel.where({ id }).find();
      }
      if (user.status !== 1) return this.json({ code: 1, msg: '账号已被停用' });

      const token = jwt.sign(
        { id: user.id, open_id: user.open_id || '', type: 'mp' },
        Base.JWT_SECRET, { expiresIn: 7 * 24 * 60 * 60 }
      );
      let patient = null;
      if (user.patient_id) {
        patient = await this.model('patient')
          .field('id, patient_no, name, phone, status, auth_status')
          .where({ id: user.patient_id, is_deleted: 0 }).find();
        if (think.isEmpty(patient)) patient = null;
      }
      return this.json({ code: 0, data: { token, userInfo: {
        id: user.id, nickname: user.nickname || '', avatar: user.avatar || '',
        phone: user.phone || mobile, patient_id: user.patient_id || null, patient
      }}});
    } catch (error) {
      think.logger.error('phoneLogin error:', error);
      return this.json({ code: 1, msg: error.message || '登录失败' });
    }
  }

  // GET /api/mp/userinfo
  async userinfoAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    try {
      const user = await this.model('wechat_user').where({ id: mpUser.id, status: 1 }).find();
      if (think.isEmpty(user)) return this.json({ code: 1009, msg: '用户不存在' });
      let patient = null;
      if (user.patient_id) {
        patient = await this.model('patient')
          .field('id, patient_no, name, phone, status, auth_status')
          .where({ id: user.patient_id, is_deleted: 0 }).find();
        if (think.isEmpty(patient)) patient = null;
      }
      return this.json({ code: 0, data: {
        id: user.id, nickname: user.nickname || '', avatar: user.avatar || '',
        phone: user.phone || '', patient_id: user.patient_id || null, patient
      }});
    } catch (error) {
      think.logger.error('userinfo error:', error);
      return this.json({ code: 1, msg: '获取用户信息失败' });
    }
  }

  // POST /api/mp/upload
  async uploadAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
    let file = this.file('file');
    let filePath = file ? file.path : '';
    if (!filePath) {
      await sleep(1000);
      file = this.file('file');
      filePath = file ? file.path : '';
      if (!filePath) return this.json({ code: 1, msg: '请选择要上传的文件' });
    }
    try {
      const originalName = file.name;
      const mimeType = file.type;
      const now = new Date();
      const dateFolder = now.getFullYear() + '/' + String(now.getMonth() + 1).padStart(2, '0') + '/' + String(now.getDate()).padStart(2, '0');
      const ext = path.extname(originalName);
      const baseName = path.basename(originalName, ext);
      const fileName = baseName + '_' + Date.now() + ext;
      const cosKey = 'uploads/' + dateFolder + '/' + fileName;
      const cos = new COS({ SecretId: cosConfig.secretId, SecretKey: cosConfig.secretKey });
      const uploadResult = await new Promise((resolve, reject) => {
        cos.putObject({
          Bucket: cosConfig.bucket, Region: cosConfig.region, Key: cosKey,
          Body: fs.createReadStream(filePath), ContentType: mimeType
        }, (err, data) => { if (err) reject(err); else resolve(data); });
      });
      setTimeout(() => { try { if (fs.existsSync(filePath)) fs.unlinkSync(filePath); } catch (e) {} }, 1000);
      if (uploadResult.statusCode === 200) {
        const bucketUrl = 'https://' + uploadResult.Location;
        const cdnUrl = bucketUrl.replace(cosConfig.bucketUrl, cosConfig.cdnUrl);
        return this.json({ code: 0, data: { url: cdnUrl } });
      }
      return this.json({ code: 1, msg: '文件上传失败' });
    } catch (error) {
      think.logger.error('upload error:', error);
      if (file && file.path && fs.existsSync(file.path)) { try { fs.unlinkSync(file.path); } catch (e) {} }
      return this.json({ code: 1, msg: '文件上传失败: ' + error.message });
    }
  }
  // POST /api/mp/sendSmsCode
  async sendSmsCodeAction() {
    const { mobile, bizType = 'real_name_auth' } = this.post();
    // login 场景不需要登录态
    if (bizType !== 'login') {
      const mpUser = this.mpUser;
      if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    }
    if (!mobile || !/^1[3-9]\d{9}$/.test(mobile)) {
      return this.json({ code: 1, msg: '请输入正确的手机号' });
    }
    const result = await this.sendSmsCode(mobile, bizType);
    if (!result.success) return this.json({ code: 1, msg: result.message });
    const smsConfig = require('../config/sms.js');
    const data = smsConfig.enabled ? {} : { code: result.code };
    return this.json({ code: 0, data, msg: result.message });
  }

  // GET /api/mp/authInfo
  async authInfoAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    try {
      const user = await this.model('wechat_user').where({ id: mpUser.id, status: 1 }).find();
      if (think.isEmpty(user) || !user.patient_id) return this.json({ code: 0, data: { authStatus: 0 } });
      const patient = await this.model('patient').where({ id: user.patient_id, is_deleted: 0 }).find();
      if (think.isEmpty(patient)) return this.json({ code: 0, data: { authStatus: 0 } });
      return this.json({ code: 0, data: {
        authStatus: patient.auth_status || 0,
        idCardType: patient.id_card_type || 1,
        idCardFront: patient.id_card_front || '',
        idCardBack: patient.id_card_back || '',
        photo: patient.photo || '',
        realName: patient.name || '',
        idCard: patient.id_card || '',
        gender: patient.gender || '',
        birthday: patient.birth_date || '',
        issuingAuthority: patient.issuing_authority || '',
        validPeriod: patient.valid_period || '',
        phone: patient.phone || '',
        authTime: patient.auth_time || ''
      }});
    } catch (error) {
      think.logger.error('authInfo error:', error);
      return this.json({ code: 1, msg: '获取认证信息失败' });
    }
  }
  // POST /api/mp/authSubmit
  async authSubmitAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    const { idCardType, idCardFront, idCardBack, photo, realName, idCard, gender, birthday, issuingAuthority, validPeriod, mobile, code, confirmBind } = this.post();
    if (!realName) return this.json({ code: 1, msg: '请输入证件姓名' });
    if (!idCard) return this.json({ code: 1, msg: '请输入证件号码' });
    const cardTypeInt = parseInt(idCardType) || 1;
    if (cardTypeInt === 2) {
      if (!photo) return this.json({ code: 1, msg: '请上传免冠照片' });
    } else {
      if (!idCardFront) return this.json({ code: 1, msg: '请上传证件正面照片' });
      if (!idCardBack) return this.json({ code: 1, msg: '请上传证件反面照片' });
    }
    if (!mobile || !/^1[3-9]\d{9}$/.test(mobile)) return this.json({ code: 1, msg: '请输入正确的手机号' });

    // 确认绑定时跳过验证码校验（第一次提交时已校验过）
    if (!confirmBind) {
      if (!code || !/^\d{6}$/.test(code)) return this.json({ code: 1, msg: '请输入6位验证码' });
      const verifyResult = await this.verifySmsCode(mobile, 'real_name_auth', code);
      if (!verifyResult.success) return this.json({ code: 1, msg: verifyResult.message });
    }

    const patientModel = this.model('patient');
    const userModel = this.model('wechat_user');
    const currentUser = await userModel.where({ id: mpUser.id }).find();

    // 排除当前用户已绑定的 patient
    const excludeId = currentUser.patient_id || 0;

    // 查找身份证是否已存在
    const idCardCondition = { id_card: idCard, is_deleted: 0 };
    if (excludeId) idCardCondition.id = ['!=', excludeId];
    const existByIdCard = await patientModel.where(idCardCondition).find();

    // 查找手机号是否已存在
    const phoneCondition = { phone: mobile, is_deleted: 0 };
    if (excludeId) phoneCondition.id = ['!=', excludeId];
    const existByPhone = await patientModel.where(phoneCondition).find();

    if (!think.isEmpty(existByIdCard)) {
      if (existByIdCard.phone === mobile) {
        // 手机号+身份证都匹配 → 可绑定已有患者
        if (!confirmBind) {
          const maskedName = existByIdCard.name.length > 1
            ? existByIdCard.name[0] + '*'.repeat(existByIdCard.name.length - 1)
            : existByIdCard.name;
          const maskedPhone = '****' + existByIdCard.phone.slice(-4);
          return this.json({
            code: 1010,
            data: { patientName: maskedName, patientPhone: maskedPhone },
            msg: '该用户信息已存在'
          });
        }
        // 用户确认绑定
        const boundUser = await userModel.where({
          patient_id: existByIdCard.id,
          id: ['!=', mpUser.id],
          open_id: ['NOT LIKE', 'h5_%'],
          status: 1
        }).find();
        if (!think.isEmpty(boundUser)) {
          return this.json({ code: 1, msg: '该患者信息已被其他微信账号绑定' });
        }
        const now = think.datetime(new Date());
        await userModel.where({ id: mpUser.id }).update({ patient_id: existByIdCard.id, update_time: now });
        await patientModel.where({ id: existByIdCard.id }).update({
          name: realName, phone: mobile, id_card_type: cardTypeInt,
          id_card_front: idCardFront || '', id_card_back: idCardBack || '', photo: photo || '',
          gender: gender || '', birth_date: birthday || null,
          issuing_authority: issuingAuthority || '', valid_period: validPeriod || '',
          auth_status: 1, auth_time: now, update_time: now
        });
        return this.json({ code: 0, data: {}, msg: '实名认证成功' });
      }
      // 身份证存在但手机号不同
      return this.json({ code: 1, msg: '该证件号已被其他用户认证' });
    }

    // 身份证不存在，但手机号已被其他患者使用
    if (!think.isEmpty(existByPhone)) {
      return this.json({ code: 1, msg: '该手机号已被其他患者使用' });
    }

    if (cardTypeInt === 1 || cardTypeInt === 3) {
      const faceidConfig = require('../config/faceid.js');
      if (faceidConfig.enabled) {
        const verifyIdResult = await this._verifyIdCard(realName, idCard);
        if (!verifyIdResult.success) return this.json({ code: 1, msg: verifyIdResult.message });
      }
    }

    const now = think.datetime(new Date());
    try {
      if (currentUser.patient_id) {
        await patientModel.where({ id: currentUser.patient_id }).update({
          name: realName, phone: mobile, id_card: idCard, id_card_type: cardTypeInt,
          id_card_front: idCardFront || '', id_card_back: idCardBack || '', photo: photo || '',
          gender: gender || '', birth_date: birthday || null,
          issuing_authority: issuingAuthority || '', valid_period: validPeriod || '',
          auth_status: 1, auth_time: now, update_time: now
        });
      } else {
        const patientNo = patientModel.generatePatientNo();
        const patientId = await patientModel.add({
          patient_no: patientNo, name: realName, phone: mobile, id_card: idCard,
          id_card_type: cardTypeInt, id_card_front: idCardFront || '', id_card_back: idCardBack || '',
          photo: photo || '', gender: gender || '', birth_date: birthday || null,
          issuing_authority: issuingAuthority || '', valid_period: validPeriod || '',
          auth_status: 1, auth_time: now, status: -1, is_deleted: 0, create_time: now, update_time: now
        });
        await userModel.where({ id: mpUser.id }).update({ patient_id: patientId, update_time: now });
      }
      return this.json({ code: 0, data: {}, msg: '实名认证成功' });
    } catch (error) {
      think.logger.error('authSubmit error:', error);
      return this.json({ code: 1, msg: '认证失败: ' + error.message });
    }
  }
  // GET /api/mp/myInfo
  async myInfoAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    try {
      const user = await this.model('wechat_user').where({ id: mpUser.id, status: 1 }).find();
      if (think.isEmpty(user) || !user.patient_id) return this.json({ code: 0, data: null });
      const patient = await this.model('patient').where({ id: user.patient_id, is_deleted: 0 }).find();
      if (think.isEmpty(patient)) return this.json({ code: 0, data: null });

      const codes = [patient.province_code, patient.city_code, patient.district_code].filter(Boolean);
      const regionMap = {};
      if (codes.length) {
        const regions = await this.model('sys_region').where({ code: ['in', codes] }).select();
        regions.forEach(r => { regionMap[r.code] = r.name; });
      }
      let documents = [];
      try { documents = JSON.parse(patient.documents || '[]'); } catch (e) { documents = []; }

      // 如果是驳回状态，查最近一条驳回原因
      let rejectReason = '';
      if (patient.status === 2) {
        const audit = await this.model('patient_audit')
          .where({ patient_id: user.patient_id, action: 'reject' })
          .order('id DESC')
          .find();
        if (!think.isEmpty(audit)) rejectReason = audit.reason || '';
      }

      return this.json({ code: 0, data: {
        name: patient.name || '', id_card: patient.id_card || '', phone: patient.phone || '',
        gender: patient.gender || '', birth_date: patient.birth_date || '',
        province_code: patient.province_code || '', city_code: patient.city_code || '',
        district_code: patient.district_code || '',
        province_name: regionMap[patient.province_code] || '',
        city_name: regionMap[patient.city_code] || '',
        district_name: regionMap[patient.district_code] || '',
        address: patient.address || '',
        emergency_contact: patient.emergency_contact || '',
        emergency_phone: patient.emergency_phone || '',
        tag: patient.tag || '', documents,
        sign_income: patient.sign_income || '',
        sign_privacy: patient.sign_privacy || '',
        sign_privacy_jhr: patient.sign_privacy_jhr || '',
        sign_promise: patient.sign_promise || '',
        income_amount: patient.income_amount || '',
        guardian_name: patient.guardian_name || '',
        guardian_id_card: patient.guardian_id_card || '',
        guardian_relation: patient.guardian_relation || '',
        status: patient.status, auth_status: patient.auth_status || 0,
        reject_reason: rejectReason
      }});
    } catch (error) {
      think.logger.error('myInfo error:', error);
      return this.json({ code: 1, msg: '获取资料失败' });
    }
  }

  // POST /api/mp/saveMyInfo
  async saveMyInfoAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    const { gender, province_code, city_code, district_code, address, emergency_contact, emergency_phone, documents, sign_income, sign_privacy, sign_privacy_jhr, sign_promise, income_amount, guardian_name, guardian_id_card, guardian_relation, mp_env_version } = this.post();
    const user = await this.model('wechat_user').where({ id: mpUser.id, status: 1 }).find();
    if (think.isEmpty(user) || !user.patient_id) return this.json({ code: 1, msg: '请先完成实名认证' });
    if (!province_code || !city_code || !district_code) return this.json({ code: 1, msg: '请选择省市区' });
    if (!address) return this.json({ code: 1, msg: '请填写详细地址' });

    const now = think.datetime(new Date());
    try {
      // 更新小程序版本标识（用于订阅消息推送到对应版本）
      if (mp_env_version) {
        await this.model('wechat_user').where({ id: mpUser.id }).update({ mp_env_version });
      }
      await this.model('patient').where({ id: user.patient_id }).update({
        gender: gender || '', province_code: province_code || '', city_code: city_code || '',
        district_code: district_code || '', address: address || '',
        emergency_contact: emergency_contact || '', emergency_phone: emergency_phone || '',
        documents: JSON.stringify(documents || []),
        sign_income: sign_income || '',
        sign_privacy: sign_privacy || '',
        sign_privacy_jhr: sign_privacy_jhr || '',
        sign_promise: sign_promise || '',
        income_amount: income_amount || null,
        guardian_name: guardian_name || '',
        guardian_id_card: guardian_id_card || '',
        guardian_relation: guardian_relation || '',
        status: 0,
        update_time: now
      });
      // 记录提交审核日志
      await this.model('patient_audit').add({
        patient_id: user.patient_id,
        action: 'submit',
        operator_id: 0,
        operator_name: '用户自助提交'
      });

      // 异步 OCR 识别瘤种（不阻塞用户提交）
      const patientId = user.patient_id;
      const docUrls = documents || [];
      if (docUrls.length) {
        setImmediate(async () => {
          try {
            const tagOptions = await think.model('sys_config').getByKey('tag_options');
            if (tagOptions && tagOptions.length) {
              const ocrService = think.service('ocr');
              const matchedTag = await ocrService.matchTag(docUrls, tagOptions);
              if (matchedTag) {
                await think.model('patient').where({ id: patientId }).update({ tag: matchedTag });
                think.logger.info(`[OCR] 患者(ID:${patientId}) 识别瘤种: ${matchedTag}`);
              }
            }
          } catch (err) {
            think.logger.error(`[OCR] 患者(ID:${patientId}) 识别失败:`, err.message);
          }
        });
      }

      return this.json({ code: 0, data: {}, msg: '提交成功' });
    } catch (error) {
      think.logger.error('saveMyInfo error:', error);
      return this.json({ code: 1, msg: '保存失败: ' + error.message });
    }
  }
  // POST /api/mp/changePhone
  async changePhoneAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    const { mobile, code } = this.post();
    if (!mobile || !/^1[3-9]\d{9}$/.test(mobile)) return this.json({ code: 1, msg: '请输入正确的手机号' });
    if (!code || !/^\d{6}$/.test(code)) return this.json({ code: 1, msg: '请输入6位验证码' });
    const verifyResult = await this.verifySmsCode(mobile, 'change_phone', code);
    if (!verifyResult.success) return this.json({ code: 1, msg: verifyResult.message });
    const now = think.datetime(new Date());
    const userModel = this.model('wechat_user');
    try {
      await userModel.where({ id: mpUser.id }).update({ phone: mobile, update_time: now });
      const user = await userModel.where({ id: mpUser.id }).find();
      if (user.patient_id) {
        await this.model('patient').where({ id: user.patient_id }).update({ phone: mobile, update_time: now });
      }
      return this.json({ code: 0, data: {}, msg: '手机号修改成功' });
    } catch (error) {
      think.logger.error('changePhone error:', error);
      return this.json({ code: 1, msg: '修改失败: ' + error.message });
    }
  }

  // POST /api/mp/sign - 签署协议，生成合成图返回URL（不写库）
  async signAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    const { type, signImage, amount, guardianName, guardianIdCard, guardianRelation } = this.post();
    const validTypes = ['income', 'privacy', 'privacy_jhr', 'promise'];
    if (!validTypes.includes(type)) return this.json({ code: 1, msg: '签署类型错误' });
    if (!signImage) return this.json({ code: 1, msg: '请先签名' });
    if (type === 'income' && (!amount || Number(amount) <= 0)) {
      return this.json({ code: 1, msg: '请填写有效的收入金额' });
    }
    if (type === 'privacy_jhr') {
      if (!guardianName) return this.json({ code: 1, msg: '请输入监护人姓名' });
      if (!guardianIdCard) return this.json({ code: 1, msg: '请输入监护人身份证号' });
      if (!guardianRelation) return this.json({ code: 1, msg: '请输入与患者关系' });
    }

    try {
      // 获取患者姓名
      const user = await this.model('wechat_user').where({ id: mpUser.id, status: 1 }).find();
      if (think.isEmpty(user) || !user.patient_id) return this.json({ code: 1, msg: '请先完成实名认证' });
      const patient = await this.model('patient').field('name, id_card').where({ id: user.patient_id, is_deleted: 0 }).find();
      if (think.isEmpty(patient)) return this.json({ code: 1, msg: '患者信息不存在' });

      // 获取协议内容
      const contentKey = 'sign_' + type;
      const doc = await this.model('content').getByKey(contentKey);
      if (think.isEmpty(doc)) return this.json({ code: 1, msg: '协议内容未配置' });

      const signTime = think.datetime(new Date());

      // 调用截图服务生成合成图
      const screenshotService = this.service('screenshot');
      const generateParams = {
        title: doc.title,
        content: doc.content,
        signImageUrl: signImage,
        signerName: patient.name,
        signerIdCard: patient.id_card,
        signTime,
        amount: type === 'income' ? amount : null
      };
      // 监护人类型传递额外字段
      if (type === 'privacy_jhr') {
        generateParams.guardianName = guardianName;
        generateParams.guardianIdCard = guardianIdCard;
        generateParams.guardianRelation = guardianRelation;
      }
      const url = await screenshotService.generate(generateParams);

      return this.json({ code: 0, data: { url }, msg: '签署成功' });
    } catch (error) {
      think.logger.error('sign error:', error);
      return this.json({ code: 1, msg: '签署失败: ' + error.message });
    }
  }

  // POST /api/mp/updateAvatar - 更新头像
  async updateAvatarAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    const { avatar } = this.post();
    if (!avatar) return this.json({ code: 1, msg: '请上传头像' });
    const now = think.datetime(new Date());
    try {
      await this.model('wechat_user').where({ id: mpUser.id }).update({ avatar, update_time: now });
      return this.json({ code: 0, data: { avatar }, msg: '头像更新成功' });
    } catch (error) {
      think.logger.error('updateAvatar error:', error);
      return this.json({ code: 1, msg: '更新失败: ' + error.message });
    }
  }

  // GET /api/mp/messages - 消息列表
  async messagesAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    const { page = 1, pageSize = 20 } = this.get();
    try {
      const user = await this.model('wechat_user').where({ id: mpUser.id, status: 1 }).find();
      if (think.isEmpty(user) || !user.patient_id) return this.json({ code: 0, data: { data: [], count: 0, totalPages: 0, currentPage: 1 } });
      const list = await this.model('message')
        .where({ patient_id: user.patient_id })
        .order('id DESC')
        .page(page, pageSize)
        .countSelect();
      return this.json({ code: 0, data: list });
    } catch (error) {
      think.logger.error('messages error:', error);
      return this.json({ code: 1, msg: '获取消息失败' });
    }
  }

  // GET /api/mp/messageDetail - 消息详情（同时标记已读）
  async messageDetailAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    const { id } = this.get();
    if (!id) return this.json({ code: 1, msg: '参数错误' });
    try {
      const user = await this.model('wechat_user').where({ id: mpUser.id, status: 1 }).find();
      if (think.isEmpty(user) || !user.patient_id) return this.json({ code: 1, msg: '无权访问' });
      const msg = await this.model('message').where({ id, patient_id: user.patient_id }).find();
      if (think.isEmpty(msg)) return this.json({ code: 1, msg: '消息不存在' });
      // 标记已读
      if (!msg.is_read) {
        await this.model('message').where({ id }).update({ is_read: 1 });
      }
      // 查患者姓名
      const patient = await this.model('patient').field('name').where({ id: user.patient_id }).find();
      msg.patient_name = patient ? patient.name : '';
      return this.json({ code: 0, data: msg });
    } catch (error) {
      think.logger.error('messageDetail error:', error);
      return this.json({ code: 1, msg: '获取消息详情失败' });
    }
  }

  // GET /api/mp/unreadCount - 未读消息数
  async unreadCountAction() {
    const mpUser = this.mpUser;
    if (!mpUser) return this.json({ code: 1009, msg: '请先登录' });
    try {
      const user = await this.model('wechat_user').where({ id: mpUser.id, status: 1 }).find();
      if (think.isEmpty(user) || !user.patient_id) return this.json({ code: 0, data: { count: 0 } });
      const count = await this.model('message').where({ patient_id: user.patient_id, is_read: 0 }).count();
      return this.json({ code: 0, data: { count } });
    } catch (error) {
      think.logger.error('unreadCount error:', error);
      return this.json({ code: 0, data: { count: 0 } });
    }
  }

  // GET /api/mp/subscribeConfig - 获取订阅消息模板配置
  async subscribeConfigAction() {
    try {
      const wechatService = this.service('wechat');
      const templates = await wechatService.getSubscribeTemplates(APP_REMARK);
      return this.json({ code: 0, data: templates });
    } catch (error) {
      think.logger.error('subscribeConfig error:', error);
      return this.json({ code: 0, data: {} });
    }
  }

  // @private
  async _verifyIdCard(name, idCard) {
    const faceidConfig = require('../config/faceid.js');
    try {
      const tencentcloud = require('tencentcloud-sdk-nodejs');
      const FaceidClient = tencentcloud.faceid.v20180301.Client;
      const client = new FaceidClient({
        credential: { secretId: faceidConfig.secretId, secretKey: faceidConfig.secretKey },
        region: faceidConfig.region,
        profile: { httpProfile: { endpoint: 'faceid.tencentcloudapi.com' } }
      });
      const result = await client.IdCardVerification({ IdCard: idCard, Name: name });
      if (result.Result === '0') return { success: true, message: '身份核验通过' };
      if (result.Result === '1') return { success: false, message: '姓名与身份证号不匹配' };
      if (result.Result === '2') return { success: false, message: '身份证号格式错误' };
      if (result.Result === '3') return { success: false, message: '姓名格式错误' };
      return { success: false, message: result.Description || '身份核验失败' };
    } catch (error) {
      think.logger.error('[FaceId] verify error:', error);
      return { success: false, message: error.message || '身份核验服务异常' };
    }
  }
};
