const Base = require('../base.js');
const dayjs = require('dayjs');

module.exports = class extends Base {
  // 患者列表页面
  async indexAction() {
    this.assign('currentPage', 'patient');
    this.assign('pageTitle', '患者管理');
    this.assign('breadcrumb', [{ name: '患者管理' }]);
    this.assign('adminUser', this.adminUser || {});
    this.assign('canAdd', this.isSuperAdmin || (this.userPermissions || []).includes('patient:add'));
    this.assign('canEdit', this.isSuperAdmin || (this.userPermissions || []).includes('patient:edit'));
    this.assign('canExport', this.isSuperAdmin || (this.userPermissions || []).includes('patient:export'));
    this.assign('canAudit', this.isSuperAdmin || (this.userPermissions || []).includes('patient:audit'));
    this.assign('canView', this.isSuperAdmin || (this.userPermissions || []).includes('patient:view'));
    this.assign('canDelete', this.isSuperAdmin || (this.userPermissions || []).includes('patient:delete'));
    return this.display();
  }

  // 获取患者列表接口
  async listAction() {
    const { keyword, tag, status, startDate, endDate, province_code, city_code, district_code, page = 1, pageSize = 10 } = this.get();
    const model = this.model('patient');
    const list = await model.getList({ keyword, tag, status, startDate, endDate, province_code, city_code, district_code, page, pageSize });

    // 收集所有省市区 code 批量查询名称
    const allCodes = new Set();
    list.data.forEach(item => {
      if (item.province_code) allCodes.add(item.province_code);
      if (item.city_code) allCodes.add(item.city_code);
      if (item.district_code) allCodes.add(item.district_code);
    });
    const regionMap = {};
    if (allCodes.size) {
      const regions = await this.model('sys_region')
        .where({ code: ['in', [...allCodes]] })
        .select();
      regions.forEach(r => { regionMap[r.code] = r.name; });
    }

    // 脱敏 + 拼接地区
    list.data.forEach(item => {
      if (item.id_card && item.id_card.length === 18) {
        item.id_card_mask = item.id_card.slice(0, 3) + '***********' + item.id_card.slice(-4);
      } else {
        item.id_card_mask = item.id_card || '';
      }
      if (item.phone && item.phone.length === 11) {
        item.phone_mask = item.phone.slice(0, 3) + '****' + item.phone.slice(-4);
      } else {
        item.phone_mask = item.phone || '';
      }
      const pName = regionMap[item.province_code] || '';
      const cName = regionMap[item.city_code] || '';
      const dName = regionMap[item.district_code] || '';
      item.region_name = [pName, cName, dName].filter(Boolean).join(' ');
    });

    const counts = await model.getStatusCounts({ keyword, tag, startDate, endDate, province_code, city_code, district_code });
    return this.success({ ...list, counts });
  }

  // 患者详情页面
  async detailAction() {
    const { id } = this.get();
    if (!id) return this.redirect('/admin/patient.html');

    this.assign('currentPage', 'patient');
    this.assign('pageTitle', '患者详情');
    this.assign('breadcrumb', [
      { name: '患者管理', url: '/admin/patient.html' },
      { name: '患者详情' }
    ]);
    this.assign('patientId', id);
    this.assign('adminUser', this.adminUser || {});
    this.assign('canAudit', this.isSuperAdmin || (this.userPermissions || []).includes('patient:audit'));
    return this.display();
  }

  // 获取患者详情接口（不脱敏）
  async infoAction() {
    const { id } = this.get();
    if (!id) return this.fail('参数错误');

    const patient = await this.model('patient')
      .where({ id, is_deleted: 0 })
      .find();

    if (think.isEmpty(patient)) {
      return this.fail('患者不存在');
    }

    // 解析 JSON 字段
    try {
      patient.documents = JSON.parse(patient.documents || '[]');
    } catch (e) {
      patient.documents = [];
    }

    // 查询省市区名称
    if (patient.province_code || patient.city_code || patient.district_code) {
      const codes = [patient.province_code, patient.city_code, patient.district_code].filter(Boolean);
      if (codes.length) {
        const regions = await this.model('sys_region')
          .where({ code: ['in', codes] })
          .select();
        const regionMap = {};
        regions.forEach(r => { regionMap[r.code] = r.name; });
        patient.province_name = regionMap[patient.province_code] || '';
        patient.city_name = regionMap[patient.city_code] || '';
        patient.district_name = regionMap[patient.district_code] || '';
      }
    }

    // 获取审核记录
    const audits = await this.model('patient_audit')
      .where({ patient_id: id })
      .order('id DESC')
      .select();

    return this.success({ patient, audits });
  }

  // 新增患者
  async addAction() {
    const data = this.post();
    const { name, phone, id_card, gender, birth_date, province_code, city_code, district_code, address, emergency_contact, emergency_phone, tag, documents, sign_income, sign_privacy, sign_promise, sign_privacy_jhr, income_amount, guardian_name, guardian_id_card, guardian_relation } = data;

    if (!name || !phone || !id_card || !gender || !birth_date) {
      return this.fail('请填写完整信息');
    }

    if (!province_code || !city_code || !district_code) {
      return this.fail('请选择省市区');
    }

    if (!address) {
      return this.fail('请填写详细地址');
    }

    if (!/^1\d{10}$/.test(phone)) {
      return this.fail('手机号格式不正确');
    }

    if (!/^\d{17}[\dXx]$/.test(id_card)) {
      return this.fail('身份证号格式不正确');
    }

    const model = this.model('patient');

    // 唯一性校验
    const existByIdCardAndPhone = await model.where({ id_card, phone, is_deleted: 0 }).find();
    if (!think.isEmpty(existByIdCardAndPhone)) {
      return this.fail('该患者已存在（身份证+手机号匹配）');
    }
    const existByPhone = await model.where({ phone, is_deleted: 0 }).find();
    if (!think.isEmpty(existByPhone)) {
      return this.fail('该手机号已被其他患者使用');
    }
    const existByIdCard = await model.where({ id_card, is_deleted: 0 }).find();
    if (!think.isEmpty(existByIdCard)) {
      return this.fail('该身份证号已被其他患者使用');
    }

    const patientNo = model.generatePatientNo();

    const id = await model.add({
      patient_no: patientNo,
      name,
      phone,
      id_card,
      gender,
      birth_date,
      province_code: province_code || '',
      city_code: city_code || '',
      district_code: district_code || '',
      address: address || '',
      emergency_contact: emergency_contact || '',
      emergency_phone: emergency_phone || '',
      tag: tag || '',
      documents: JSON.stringify(documents || []),
      sign_income: sign_income || '',
      sign_privacy: sign_privacy || '',
      sign_promise: sign_promise || '',
      sign_privacy_jhr: sign_privacy_jhr || '',
      income_amount: income_amount || '',
      guardian_name: guardian_name || '',
      guardian_id_card: guardian_id_card || '',
      guardian_relation: guardian_relation || '',
      status: 1,
      create_by: this.adminUser?.id || 0
    });

    // 记录审核日志（后台新增直接审核通过）
    await this.model('patient_audit').add({
      patient_id: id,
      action: 'approve',
      operator_id: this.adminUser?.id || 0,
      operator_name: this.adminUser?.nickname || this.adminUser?.username || ''
    });

    await this.log('add', '患者管理', `新增患者「${name}」编号:${patientNo}`);
    return this.success({ id, patient_no: patientNo });
  }

  // 审核通过
  async approveAction() {
    const { id } = this.post();
    if (!id) return this.fail('参数错误');

    const patient = await this.model('patient')
      .where({ id, is_deleted: 0 })
      .find();

    if (think.isEmpty(patient)) return this.fail('患者不存在');
    if (patient.status === 1) return this.fail('该患者已审核通过');

    await this.model('patient').where({ id }).update({
      status: 1,
      update_by: this.adminUser?.id || 0
    });

    await this.model('patient_audit').add({
      patient_id: id,
      action: 'approve',
      operator_id: this.adminUser?.id || 0,
      operator_name: this.adminUser?.nickname || this.adminUser?.username || ''
    });

    // 发送消息通知
    await this.model('message').add({
      patient_id: id,
      type: 1,
      title: '审核通过',
      content: '您提交的个人资料已审核通过。',
      reason: ''
    });

    // 发送订阅消息
    await this._sendAuditSubscribeMessage(id, patient.name, '审核通过');

    // 发送短信通知
    await this._sendAuditSms(patient.phone, 'approved');

    await this.log('edit', '患者管理', `审核通过患者(ID:${id})`);
    return this.success();
  }

  // 驳回
  async rejectAction() {
    const { id, reason } = this.post();
    if (!id) return this.fail('参数错误');
    if (!reason) return this.fail('请填写驳回原因');

    const patient = await this.model('patient')
      .where({ id, is_deleted: 0 })
      .find();

    if (think.isEmpty(patient)) return this.fail('患者不存在');
    if (patient.status === 2) return this.fail('该患者已被驳回');

    await this.model('patient').where({ id }).update({
      status: 2,
      update_by: this.adminUser?.id || 0
    });

    await this.model('patient_audit').add({
      patient_id: id,
      action: 'reject',
      reason,
      operator_id: this.adminUser?.id || 0,
      operator_name: this.adminUser?.nickname || this.adminUser?.username || ''
    });

    // 发送消息通知
    await this.model('message').add({
      patient_id: id,
      type: 2,
      title: '审核未通过',
      content: '您提交的个人资料未通过审核，请根据以下原因修改后重新提交。',
      reason: reason
    });

    // 发送订阅消息
    await this._sendAuditSubscribeMessage(id, patient.name, '审核驳回');

    // 发送短信通知
    await this._sendAuditSms(patient.phone, 'rejected', reason);

    await this.log('edit', '患者管理', `驳回患者(ID:${id})，原因：${reason}`);
    return this.success();
  }

  // 删除患者（软删除，支持批量）
  async deleteAction() {
    const { ids } = this.post();
    if (!ids || !ids.length) return this.fail('参数错误');

    const model = this.model('patient');
    const patients = await model.where({ id: ['in', ids], is_deleted: 0 }).select();
    if (!patients.length) return this.fail('患者不存在');

    await model.where({ id: ['in', ids] }).update({
      is_deleted: 1,
      update_by: this.adminUser?.id || 0
    });

    // 清除 wechat_user 表中的患者关联，避免用户重新认证时走 update 逻辑
    await this.model('wechat_user')
      .where({ patient_id: ['in', ids] })
      .update({ patient_id: 0 });

    const names = patients.map(p => p.name).join('、');
    await this.log('delete', '患者管理', `删除患者「${names}」共${patients.length}条`);
    return this.success();
  }

  // 编辑患者
  async editAction() {
    const data = this.post();
    const { id, name, phone, id_card, gender, birth_date, province_code, city_code, district_code, address, emergency_contact, emergency_phone, tag, documents, sign_income, sign_privacy, sign_promise, sign_privacy_jhr, income_amount, guardian_name, guardian_id_card, guardian_relation } = data;

    if (!id) return this.fail('参数错误');
    if (!name || !phone || !id_card || !gender || !birth_date) return this.fail('请填写完整信息');
    if (!province_code || !city_code || !district_code) return this.fail('请选择省市区');
    if (!address) return this.fail('请填写详细地址');
    if (!/^1\d{10}$/.test(phone)) return this.fail('手机号格式不正确');
    if (!/^\d{17}[\dXx]$/.test(id_card)) return this.fail('身份证号格式不正确');

    const patient = await this.model('patient').where({ id, is_deleted: 0 }).find();
    if (think.isEmpty(patient)) return this.fail('患者不存在');

    // 唯一性校验（排除自身）
    const existByPhone = await this.model('patient').where({ phone, id: ['!=', id], is_deleted: 0 }).find();
    if (!think.isEmpty(existByPhone)) return this.fail('该手机号已被其他患者使用');
    const existByIdCard = await this.model('patient').where({ id_card, id: ['!=', id], is_deleted: 0 }).find();
    if (!think.isEmpty(existByIdCard)) return this.fail('该身份证号已被其他患者使用');

    await this.model('patient').where({ id }).update({
      name, phone, id_card, gender, birth_date,
      province_code, city_code, district_code,
      address: address || '',
      emergency_contact: emergency_contact || '',
      emergency_phone: emergency_phone || '',
      tag: tag || '',
      documents: JSON.stringify(documents || []),
      sign_income: sign_income || '',
      sign_privacy: sign_privacy || '',
      sign_promise: sign_promise || '',
      sign_privacy_jhr: sign_privacy_jhr || '',
      income_amount: income_amount || '',
      guardian_name: guardian_name || '',
      guardian_id_card: guardian_id_card || '',
      guardian_relation: guardian_relation || '',
      update_by: this.adminUser?.id || 0
    });

    await this.log('edit', '患者管理', `编辑患者「${name}」(ID:${id})`);
    return this.success();
  }

  // 导出患者数据（CSV，不脱敏）
  async exportAction() {
    const { keyword, tag, status, startDate, endDate, province_code, city_code, district_code } = this.get();
    const model = this.model('patient');
    const list = await model.getAll({ keyword, tag, status, startDate, endDate, province_code, city_code, district_code });

    // 批量查省市区名称
    const allCodes = new Set();
    list.forEach(item => {
      if (item.province_code) allCodes.add(item.province_code);
      if (item.city_code) allCodes.add(item.city_code);
      if (item.district_code) allCodes.add(item.district_code);
    });
    const regionMap = {};
    if (allCodes.size) {
      const regions = await this.model('sys_region')
        .where({ code: ['in', [...allCodes]] })
        .select();
      regions.forEach(r => { regionMap[r.code] = r.name; });
    }

    // 批量查最近一条审核记录（审核日期、驳回原因）
    const patientIds = list.map(item => item.id);
    const auditMap = {};
    if (patientIds.length) {
      const audits = await this.model('patient_audit')
        .where({ patient_id: ['in', patientIds], action: ['in', ['approve', 'reject']] })
        .order('id DESC')
        .select();
      audits.forEach(a => {
        if (!auditMap[a.patient_id]) auditMap[a.patient_id] = a;
      });
    }

    const statusMap = { '-1': '待提交', 0: '待审核', 1: '审核通过', 2: '已驳回' };
    const header = ['ID', '姓名', '性别', '身份证', '手机号', '省份', '城市', '提交时间', '审核状态', '审核日期', '审核驳回原因', '瘤种'];

    const ExcelJS = require('exceljs');
    const workbook = new ExcelJS.Workbook();
    const sheet = workbook.addWorksheet('患者信息');

    // 表头
    sheet.addRow(header);
    // 表头样式：绿色背景、白色加粗字体（仅到瘤种列，即K列=11列）、冻结首行
    const headerRow = sheet.getRow(1);
    const colCount = header.length; // 11列
    for (let i = 1; i <= colCount; i++) {
      const cell = headerRow.getCell(i);
      cell.font = { bold: true, color: { argb: 'FFFFFFFF' } };
      cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF4CAF50' } };
      cell.alignment = { vertical: 'middle', horizontal: 'center' };
    }
    sheet.views = [{ state: 'frozen', ySplit: 1 }];

    // 边框样式
    const thinBorder = {
      top: { style: 'thin' },
      left: { style: 'thin' },
      bottom: { style: 'thin' },
      right: { style: 'thin' }
    };
    // 表头加边框
    for (let i = 1; i <= colCount; i++) {
      headerRow.getCell(i).border = thinBorder;
    }

    // 数据行
    list.forEach(item => {
      const audit = auditMap[item.id];
      const row = sheet.addRow([
        item.patient_no,
        item.name,
        item.gender,
        item.id_card,
        item.phone,
        regionMap[item.province_code] || '',
        regionMap[item.city_code] || '',
        item.create_time || '',
        statusMap[item.status] || '',
        audit ? (audit.create_time || '') : '',
        (audit && audit.action === 'reject') ? (audit.reason || '') : '',
        item.tag || ''
      ]);
      // 数据行加边框
      for (let i = 1; i <= colCount; i++) {
        row.getCell(i).border = thinBorder;
      }
    });

    // 自动列宽
    sheet.columns.forEach(col => {
      let maxLen = 10;
      col.eachCell({ includeEmpty: true }, cell => {
        const len = String(cell.value || '').length;
        if (len > maxLen) maxLen = len;
      });
      col.width = Math.min(maxLen + 4, 40);
    });

    const buffer = await workbook.xlsx.writeBuffer();
    const ts = dayjs().format('YYYYMMDDHHmmss');
    const fileName = encodeURIComponent(`患者信息_${ts}.xlsx`);

    this.ctx.set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    this.ctx.set('Content-Disposition', `attachment; filename*=UTF-8''${fileName}`);
    this.ctx.body = Buffer.from(buffer);

    await this.log('export', '患者管理', `导出患者数据 ${list.length} 条`);
  }

  // @private 发送审核结果订阅消息
  async _sendAuditSubscribeMessage(patientId, patientName, result) {
    try {
      const APP_REMARK = 'pap_mini_cytx';
      // 查找该患者关联的微信用户
      const wechatUser = await this.model('wechat_user')
        .where({ patient_id: patientId, app_remark: APP_REMARK, status: 1 })
        .find();
      if (think.isEmpty(wechatUser) || !wechatUser.open_id) return;

      const wechatService = this.service('wechat');
      const templates = await wechatService.getSubscribeTemplates(APP_REMARK);
      const templateId = templates.audit_result;
      if (!templateId) return;

      // 映射小程序版本: __wxConfig.envVersion -> miniprogram_state
      // develop -> developer, trial -> trial, release -> formal
      const envMap = { develop: 'developer', trial: 'trial', release: 'formal' };
      const miniprogramState = envMap[wechatUser.mp_env_version] || 'formal';

      const dayjs = require('dayjs');
      await wechatService.sendSubscribeMessage({
        remark: APP_REMARK,
        openid: wechatUser.open_id,
        templateId,
        page: 'pages/profile/profile',
        miniprogramState,
        data: {
          thing2: { value: '肠愈同行患者关爱' },
          thing14: { value: patientName || '用户' },
          phrase1: { value: result },
          time13: { value: dayjs().format('YYYY-MM-DD HH:mm:ss') }
        }
      });
    } catch (error) {
      // 订阅消息发送失败不影响审核流程
      think.logger.error('[Subscribe] 审核消息发送失败:', error);
    }
  }

  // @private 发送审核结果短信通知
  async _sendAuditSms(phone, type, reason) {
    if (!phone) return;
    try {
      const smsConfig = require('../../config/sms.js');
      const templates = smsConfig.templates;
      think.logger.info(`[SMS] _sendAuditSms 开始 - phone: ${phone}, type: ${type}, reason: ${reason || '(无)'}`);
      think.logger.info(`[SMS] 模板配置 - auditApproved: ${templates.auditApproved || '(空)'}, auditRejected: ${templates.auditRejected || '(空)'}`);
      if (type === 'approved' && templates.auditApproved) {
        await this.sendNotifySms(phone, templates.auditApproved, [], 'audit_approved');
      } else if (type === 'rejected' && templates.auditRejected) {
        // 驳回原因截取前15字符（短信模板变量有长度限制）
        const shortReason = (reason || '资料不符合要求').slice(0, 15);
        await this.sendNotifySms(phone, templates.auditRejected, [shortReason], 'audit_rejected');
      }
    } catch (error) {
      think.logger.error('[SMS] 审核短信发送失败:', error);
    }
  }

};
