import { Provide } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { Tags } from '../../entity/system/tags.entity';
import * as Excel from 'exceljs';
import * as path from 'path';
import { Region } from '../../entity/system/region.entity';
import { get, isArray, isObject, omit, uniq, uniqBy } from 'lodash';
import { Company } from '../../entity/users/company.entity';
import dayjs = require('dayjs');
import { Match } from '../../entity/platform/match.entity';
import { Sign } from '../../entity/platform/sign.entity';
@Provide()
export class InitThreeService {
  tags = ['20240802'];
  @InjectEntityModel(Tags)
  tagsModel: Repository<Tags>;
  @InjectEntityModel(Region)
  regionModel: Repository<Region>;
  @InjectEntityModel(Company)
  companyModel: Repository<Company>;
  @InjectEntityModel(Match)
  matchModel: Repository<Match>;
  @InjectEntityModel(Sign)
  signModel: Repository<Sign>;

  async dataToUse() {
    await this.companyModel.update({}, { status: '1' });
  }

  /**
   * 获取excel表头对应的字段
   * @returns 表格列对应字段对象
   */
  companyMeta() {
    return {
      2: 'area1',
      3: 'name',
    };
  }

  async import2021Company() {
    const p = path.resolve(__dirname, '../../../importData/20240802', '2021-专精特新-企业.xlsx');
    const tags = [...this.tags, '2021专精特新'];
    await this.importCompany(p, tags);
    await this.addTags(tags);
  }

  async import2024Company() {
    const p = path.resolve(__dirname, '../../../importData/20240802', '2024-专精特新-企业.xlsx');
    const tags = [...this.tags, '2024专精特新'];
    await this.importCompany(p, tags);
    await this.addTags(tags);
  }

  async importCompany(path, tags) {
    const wb = new Excel.Workbook();
    await wb.xlsx.readFile(path);
    const sheet = wb.getWorksheet(1);
    if (!sheet) return;
    const meta = this.companyMeta();
    let allData = [];
    sheet.eachRow((row, ri) => {
      if (ri === 1) {
        // 不处理
      } else {
        const obj = {};
        row.eachCell((cell, ci) => {
          let val = cell.value;
          const key = meta[ci];
          if (key) {
            if (isObject(val)) {
              if (isArray(get(val, 'richText'))) {
                let text = '';
                const richText = get(val, 'richText', []);
                for (const t of richText) {
                  text = `${text}${get(t, 'text')}`;
                }
                val = text;
              }
            }
            obj[key] = val;
          }
        });
        allData.push(obj);
      }
    });
    for (const i of allData) {
      // 验重,企业是否存在
      const result = await this.companyModel.createQueryBuilder().where(`name = :name`, { name: i.name }).getOne();
      if (result) {
        i.id = get(result, 'id');
        // 标签合并,之后有id的修改,没id的添加
        i.tags = get(result, 'tags', []);
        if (i.tags === null) i.tags = [];
        i.tags = uniq([...i.tags, ...tags]);
        // 有地区之后就不需要处理地区了
        i.area = get(result, 'area', []);
        if (i.area.length > 0) continue;
      }
      // #region 地区处理
      i.tags = tags;
      i.area = ['吉林省'];
      const builder = this.regionModel.createQueryBuilder();
      builder.where(`name like '%${i.area1}%'`);
      builder.andWhere("level = 'city'");
      builder.andWhere("code like '22%'");
      const r1 = await builder.getOne();
      if (r1) i.area.push(r1.name);
      // 延边州和梅河口需要特殊处理
      if (i.area1.includes('梅河口')) i.area = ['吉林省', '通化市', '梅河口市'];
      else if (i.area1.includes('延边')) i.area.push('延边朝鲜族自治州');
      // 地区处理不通过就不进行处理了
      if (i.area.length > 1) delete i.area1;
      else i.noarea = true;
    }
    allData = allData.filter(f => !f.noarea);
    const updateList = allData.filter(f => f.id);
    const insertList = allData.filter(f => !f.id);
    await this.companyModel.createQueryBuilder().insert().into(Company).values(insertList).execute();
    for (const i of updateList) {
      await this.companyModel.createQueryBuilder().update(Company).set(omit(i, 'id')).where(`id = :id`, { id: i.id }).execute();
    }
  }

  matchingMeta() {
    return {
      2: 'name',
      3: 'start_time',
      4: 'address',
      5: 'sign.name',
      6: 'sign.unit',
    };
  }

  async importMatching() {
    const p = path.resolve(__dirname, '../../../importData/20240802', '赛事信息.xlsx');
    const wb = new Excel.Workbook();
    await wb.xlsx.readFile(p);
    const sheet = wb.getWorksheet(1);
    if (!sheet) return;
    // 导入数据分两个表, 培训名称和培训时间(开始时间),培训地点都属于赛事
    // 培训人姓名和企业名称(隶属单位)都属于参赛人员部分
    const meta = this.matchingMeta();
    let allData = [];
    sheet.eachRow((row, ri) => {
      if (ri === 1) {
        // 不处理
      } else {
        const obj = {};
        row.eachCell((cell, ci) => {
          let val = cell.value;
          const key = meta[ci];
          if (key) {
            if (isObject(val)) {
              if (isArray(get(val, 'richText'))) {
                let text = '';
                const richText = get(val, 'richText', []);
                for (const t of richText) {
                  text = `${text}${get(t, 'text')}`;
                }
                val = text;
              }
            }
            obj[key] = val;
          }
        });
        allData.push(obj);
      }
    });
    let matchList = allData.map(i => ({ ...omit(i, ['sign.name', 'sign.unit', 'start_time']), start_time: dayjs(i.start_time).format('YYYY-MM-DD') }));
    matchList = uniqBy(matchList, 'name');
    for (const m of matchList) {
      const name = get(m, 'name');
      const match = await this.matchModel.createQueryBuilder().where('name = :name', { name }).getOne();
      let mid;
      // 有赛事,就合并标签
      if (match) {
        mid = match.id;
        let otags = get(match, 'tags', []);
        if (otags === null) otags = [];
        const newTags = uniq([...otags, ...this.tags]);
        const updateData: any = { tags: newTags };
        await this.matchModel.createQueryBuilder().update(Match).set(updateData).where('id = :id', { id: match.id }).execute();
      } else {
        const insertData: any = { ...m, tags: this.tags };
        const result = await this.matchModel.insert(insertData);
        mid = get(result, 'identifiers.0.id');
      }
      // 已经过滤出赛事数据 m 和 参加该赛事的人员名单 signList.接下来先创建赛事数据,然后再将赛事数据id放到各个参赛人员数据中
      let signList = allData.filter(f => f.name === name);
      signList = signList.map(i => ({ ...omit(i, ['name', 'address', 'start_time']), match: mid }));
      for (const i of signList) {
        const obj = {};
        for (const key in i) {
          const val = i[key];
          if (key.includes('sign.')) {
            const nk = key.replace('sign.', '');
            obj[nk] = val;
          } else obj[key] = val;
        }
        const num = await this.signModel.createQueryBuilder().where('name = :name', { name: i.name }).andWhere('match = :match', { match: i.match }).getCount();
        if (num <= 0) await this.signModel.insert(obj);
      }
    }
    await this.addTags(this.tags);
  }

  async addTags(tags: Array<string>) {
    const arr = [];
    for (const i of tags) {
      const num = await this.tagsModel.createQueryBuilder().where(`title = :title`, { title: i }).getCount();
      if (num > 0) continue;
      arr.push({ title: i });
    }
    if (arr.length <= 0) return;
    await this.tagsModel.createQueryBuilder().insert().into(Tags).values(arr).updateEntity(false).execute();
  }
}
