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

module.exports = class extends Base {
  async indexAction() {
    this.assign('currentPage', 'hospital');
    this.assign('pageTitle', '医院管理');
    this.assign('breadcrumb', [{ name: '医院管理' }]);
    return this.display();
  }

  // 列表（分页）
  async listAction() {
    const keyword = this.get('keyword') || '';
    const provinceCode = this.get('province_code') || '';
    const cityCode = this.get('city_code') || '';
    const districtCode = this.get('district_code') || '';
    const page = this.get('page') || 1;
    const pageSize = this.get('pageSize') || 10;
    const where = { is_deleted: 0 };
    if (keyword) where.name = ['like', `%${keyword}%`];
    if (provinceCode) where.province_code = provinceCode;
    if (cityCode) where.city_code = cityCode;
    if (districtCode) where.district_code = districtCode;
    const data = await this.model('hospital')
      .where(where)
      .order('sort DESC, id ASC')
      .page(page, pageSize)
      .countSelect();
    return this.json({ code: 0, data });
  }

  // 新增
  async addAction() {
    const { name, province_code, city_code, district_code, sort, is_show } = this.post();
    if (!name || !name.trim()) return this.fail('请输入医院名称');
    const exists = await this.model('hospital').where({ name: name.trim(), is_deleted: 0 }).find();
    if (!think.isEmpty(exists)) return this.fail('该医院已存在');
    const regionNames = await this._getRegionNames(province_code, city_code, district_code);
    await this.model('hospital').add({
      name: name.trim(),
      province_code: province_code || '',
      city_code: city_code || '',
      district_code: district_code || '',
      province_name: regionNames.province,
      city_name: regionNames.city,
      district_name: regionNames.district,
      sort: sort || 0,
      is_show: is_show === undefined ? 1 : (is_show ? 1 : 0)
    });
    await this.model('hospital').clearTreeCache();
    await this.log('add', '医院管理', `新增医院「${name.trim()}」`);
    return this.success();
  }

  // 编辑
  async editAction() {
    const { id, name, province_code, city_code, district_code, sort, is_show } = this.post();
    if (!id) return this.fail('参数错误');
    if (!name || !name.trim()) return this.fail('请输入医院名称');
    const exists = await this.model('hospital').where({ name: name.trim(), id: ['!=', id], is_deleted: 0 }).find();
    if (!think.isEmpty(exists)) return this.fail('该医院已存在');
    const regionNames = await this._getRegionNames(province_code, city_code, district_code);
    await this.model('hospital').where({ id }).update({
      name: name.trim(),
      province_code: province_code || '',
      city_code: city_code || '',
      district_code: district_code || '',
      province_name: regionNames.province,
      city_name: regionNames.city,
      district_name: regionNames.district,
      sort: sort || 0,
      is_show: is_show ? 1 : 0
    });
    await this.model('hospital').clearTreeCache();
    await this.log('edit', '医院管理', `编辑医院(ID:${id})「${name.trim()}」`);
    return this.success();
  }

  // 删除
  async deleteAction() {
    const { id } = this.post();
    if (!id) return this.fail('参数错误');
    await this.model('hospital').where({ id }).update({ is_deleted: 1 });
    await this.model('hospital').clearTreeCache();
    await this.log('delete', '医院管理', `删除医院(ID:${id})`);
    return this.success();
  }

  // 切换展示状态
  async toggleShowAction() {
    const { id, is_show } = this.post();
    if (!id) return this.fail('参数错误');
    await this.model('hospital').where({ id }).update({ is_show: is_show ? 1 : 0 });
    await this.model('hospital').clearTreeCache();
    await this.log('edit', '医院管理', `${is_show ? '展示' : '隐藏'}医院(ID:${id})`);
    return this.success();
  }

  // 排序
  async sortAction() {
    const { ids } = this.post();
    if (!ids || !ids.length) return this.fail('参数错误');
    for (let i = 0; i < ids.length; i++) {
      await this.model('hospital').where({ id: ids[i] }).update({ sort: ids.length - i });
    }
    await this.model('hospital').clearTreeCache();
    return this.success();
  }

  // Excel 导入（表头：关联机构名称/省份/城市/区县）
  async importAction() {
    const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
    let file = this.file('file');
    if (!file || !file.path) {
      await sleep(1000);
      file = this.file('file');
    }
    if (!file || !file.path) return this.fail('请上传 Excel 文件');

    const ExcelJS = require('exceljs');
    const workbook = new ExcelJS.Workbook();
    try {
      await workbook.xlsx.readFile(file.path);
    } catch (e) {
      return this.fail('文件解析失败，请上传有效的 Excel 文件');
    }
    const sheet = workbook.worksheets[0];
    if (!sheet) return this.fail('Excel 内容为空');

    // 读取数据行（跳过表头）
    const rows = [];
    sheet.eachRow((row, rowNumber) => {
      if (rowNumber === 1) return; // 表头
      const name = this._cellText(row.getCell(1));
      const province = this._cellText(row.getCell(2));
      const city = this._cellText(row.getCell(3));
      const district = this._cellText(row.getCell(4));
      if (name) rows.push({ name, province, city, district });
    });

    if (!rows.length) return this.fail('没有有效的数据行');

    // 预加载全部地区，构建名称索引
    const regions = await this.model('sys_region').where({ status: 1 }).select();
    const regionIndex = this._buildRegionIndex(regions);

    // 已存在的医院名称
    const existRows = await this.model('hospital').where({ is_deleted: 0 }).field('name').select();
    const existNames = new Set(existRows.map(r => r.name));

    const toInsert = [];
    const seen = new Set();
    const unmatched = []; // 地区未匹配的医院名
    let skipped = 0;

    rows.forEach(r => {
      if (existNames.has(r.name) || seen.has(r.name)) { skipped++; return; }
      seen.add(r.name);
      const codes = this._matchRegion(regionIndex, r.province, r.city, r.district);
      if ((r.province && !codes.province_code) || (r.city && !codes.city_code) || (r.district && !codes.district_code)) {
        unmatched.push(r.name);
      }
      toInsert.push({
        name: r.name,
        province_code: codes.province_code,
        city_code: codes.city_code,
        district_code: codes.district_code,
        province_name: r.province || '',
        city_name: r.city || '',
        district_name: r.district || '',
        sort: 0,
        is_show: 1
      });
    });

    if (!toInsert.length) return this.fail('没有新增医院（均已存在）');

    // 分批插入
    const batchSize = 200;
    for (let i = 0; i < toInsert.length; i += batchSize) {
      await this.model('hospital').addMany(toInsert.slice(i, i + batchSize));
    }
    await this.model('hospital').clearTreeCache();
    await this.log('import', '医院管理', `导入医院 ${toInsert.length} 条`);

    return this.success({
      count: toInsert.length,
      skipped,
      unmatchedCount: unmatched.length,
      unmatched: unmatched.slice(0, 50)
    });
  }

  // @private 读取单元格文本
  _cellText(cell) {
    if (!cell || cell.value === null || cell.value === undefined) return '';
    const v = cell.value;
    if (typeof v === 'object') {
      if (v.text) return String(v.text).trim();
      if (v.result !== undefined) return String(v.result).trim();
      if (v.richText) return v.richText.map(t => t.text).join('').trim();
      return '';
    }
    return String(v).trim();
  }

  // @private 构建地区名称索引：{ provinceName: {code, cities: { cityName: {code, districts: { distName: code }}}}}
  _buildRegionIndex(regions) {
    const provinces = {};
    const cityByParent = {};
    const distByParent = {};
    regions.forEach(r => {
      const code = r.code;
      if (code.endsWith('0000')) {
        provinces[r.name] = { code, cities: {} };
      } else if (code.endsWith('00')) {
        const pCode = code.substring(0, 2) + '0000';
        if (!cityByParent[pCode]) cityByParent[pCode] = [];
        cityByParent[pCode].push({ code, name: r.name });
      } else {
        const cCode = code.substring(0, 4) + '00';
        if (!distByParent[cCode]) distByParent[cCode] = [];
        distByParent[cCode].push({ code, name: r.name });
      }
    });
    // 组装
    Object.values(provinces).forEach(prov => {
      const cities = cityByParent[prov.code] || [];
      cities.forEach(c => {
        prov.cities[c.name] = { code: c.code, districts: {} };
        const dists = distByParent[c.code] || [];
        dists.forEach(d => { prov.cities[c.name].districts[d.name] = d.code; });
      });
    });
    return provinces;
  }

  // @private 名称匹配编码（容错：直辖市省市同名、模糊包含）
  _matchRegion(index, provinceName, cityName, districtName) {
    const result = { province_code: '', city_code: '', district_code: '' };
    if (!provinceName) return result;

    // 匹配省（容错：去掉"省/市/自治区"等后缀的包含匹配）
    let prov = index[provinceName];
    if (!prov) {
      const pKey = Object.keys(index).find(k => k.includes(provinceName) || provinceName.includes(k));
      if (pKey) prov = index[pKey];
    }
    if (!prov) return result;
    result.province_code = prov.code;

    // 匹配市
    let city = prov.cities[cityName];
    if (!city && cityName) {
      const cKey = Object.keys(prov.cities).find(k => k.includes(cityName) || cityName.includes(k));
      if (cKey) city = prov.cities[cKey];
    }
    // 直辖市：省名=市名，市层可能只有一个
    if (!city) {
      const cityKeys = Object.keys(prov.cities);
      if (cityKeys.length === 1) city = prov.cities[cityKeys[0]];
    }

    // 省直辖县级行政区、部分直辖市导入数据可能出现「城市=区县」：
    // 此时城市名匹配不到标准市级节点，用「省 + 区县」在该省下横向查一次。
    if (!city && districtName) {
      const matched = this._findDistrictInProvince(prov, districtName);
      if (matched) {
        result.city_code = matched.city.code;
        result.district_code = matched.districtCode;
      }
      return result;
    }
    if (!city) return result;
    result.city_code = city.code;

    // 匹配区县
    if (districtName) {
      let dCode = city.districts[districtName];
      if (!dCode) {
        const dKey = Object.keys(city.districts).find(k => k.includes(districtName) || districtName.includes(k));
        if (dKey) dCode = city.districts[dKey];
      }
      if (!dCode) {
        const matched = this._findDistrictInProvince(prov, districtName);
        if (matched) {
          result.city_code = matched.city.code;
          dCode = matched.districtCode;
        }
      }
      if (dCode) result.district_code = dCode;
    }
    return result;
  }

  // @private 在指定省份下按区县名称横向匹配，并返回其所属城市
  _findDistrictInProvince(prov, districtName) {
    if (!prov || !districtName) return null;
    for (const city of Object.values(prov.cities)) {
      let dCode = city.districts[districtName];
      if (!dCode) {
        const dKey = Object.keys(city.districts).find(k => k.includes(districtName) || districtName.includes(k));
        if (dKey) dCode = city.districts[dKey];
      }
      if (dCode) return { city, districtCode: dCode };
    }
    return null;
  }

  // @private 根据编码查地区名称
  async _getRegionNames(provinceCode, cityCode, districtCode) {
    const codes = [provinceCode, cityCode, districtCode].filter(Boolean);
    const map = {};
    if (codes.length) {
      const regions = await this.model('sys_region').where({ code: ['in', codes] }).select();
      regions.forEach(r => { map[r.code] = r.name; });
    }
    return {
      province: map[provinceCode] || '',
      city: map[cityCode] || '',
      district: map[districtCode] || ''
    };
  }
};
