
'use strict';

const Service = require('egg').Service;
const R = require('ramda');
const _ = require('lodash');
const moment = require('moment');
class InstitutionSubService extends Service {
  // 获取分类
  async getCats() {
    const { ctx } = this;

    const AllCats = await ctx.classModel.V2.CourseCat.findAll({ where: { status: 1, is_deleted: 0 } });
    const rootCats = [];
    let ret = [];

    // 先取出一级分类
    for (const v of AllCats) {
      if (v.parent_id === 0) {
        rootCats[v.id] = v.dataValues;
        rootCats[v.id].child = [{ id: 0, value: v.id, name: '全部', parent_id: 0, image: 'http://r.51gjj.com/webpublic/images/20191118/s6yRUsc5kclyu.png', active_image: 'http://r.51gjj.com/webpublic/images/20191118/zYHkYp85vxk5m.png', color: '', tips: '', status: 'online', is_deleted: 0 }];
      }
    }

    // 放入二级分类
    for (const v of AllCats) {
      if (v.parent_id > 0) {
        v.value = v.id;
        rootCats[v.parent_id].child.push(v);
      }
    }

    const sort = function(a, b) {
      return a.sort - b.sort;
    };

    // 整理
    for (const v of rootCats) {
      if (!ctx.isEmpty(v)) {
        v.child = R.sort(sort)(v.child);
        ret.push(v);
      }
    }

    ret = R.sort(sort)(ret);

    return { results: ret };
  }


  // 获取机构详情
  async getInstitution(input) {
    const { ctx } = this;
    const userUuid = ctx.userUuid;
    const { institution_id } = input;
    const lat = ctx.isEmpty(input.lat) ? 0 : input.lat;
    const lng = ctx.isEmpty(input.lng) ? 0 : input.lng;

    let institution = await ctx.classModel.V2.CourseInstitution.findOne({ where: { id: institution_id, status: 'online', is_deleted: 0 } });
    if (ctx.isEmpty(institution)) {
      ctx.failed('机构不存在');
    }
    institution = institution.dataValues;

    // 顶部相册
    const images = await ctx.classModel.V2.CourseImages.findAll({ where: { type: 1, type_id: institution_id, status: 'online', is_deleted: 0 } });
    // 去重
    const checkList = [];
    let album = [];
    for (const v of images) {
      if ((v.is_video === 0 && checkList.includes(v.image_url)) || (v.is_video === 1 && checkList.includes(v.video_url))) {
        continue;
      }
      album.push(v);
    }

    // 排序，视频在前
    const albumSort = function(a, b) {
      if (a.is_video === b.is_video) {
        return a.sort - b.sort;
      }
      return b.is_video - a.is_video;
    };
    album = R.sort(albumSort)(album);

    // 学习成果
    const student_video = await ctx.classModel.V2.CourseStudentVideo.findAll({ where: { institution_id, status: 'online', is_deleted: 0 }, order: [[ 'sort', 'asc' ]] });

    // 教师
    const teachers = await ctx.classModel.V2.CourseTeacher.findAll({ where: { institution_id, status: 'online', is_deleted: 0 }, raw: true });

    // 课程
    const classes = await ctx.classModel.V2.CourseClass.findAll({ where: { institution_id, status: 'online', is_deleted: 0 }, raw: true });
    // 处理课程封面图
    const classHandle = [];
    if (classes.length > 0) {
      for (const v of classes) {
        classHandle.push(ctx.classModel.V2.CourseImages.findOne({ where: { type: 2, type_id: v.id, status: 'online', is_deleted: 0 }, order: [[ 'sort', 'asc' ]] }));
      }
      const classImages = await Promise.all(classHandle).then(result => {
        return result;
      }).catch(error => {
        ctx.failed(error);
      });

      for (const i in classes) {
        classes[i].image = classImages[i];
      }
    }

    // 校区
    let areas = await ctx.classModel.V2.CourseArea.findAll({ where: { institution_id, status: 'online', is_deleted: 0 }, raw: true });
    const areaHandle = [];
    if (areas.length > 0) {
      for (const v of areas) {
        areaHandle.push(this.formatArea(v, { lng, lat }));
      }
      areas = await Promise.all(areaHandle).then(result => {
        return result;
      }).catch(error => {
        ctx.failed(error);
      });
    }
    areas = _.orderBy(areas, [ 'distance' ], [ 'asc' ]);

    // 是否已收藏
    const userCollect = await ctx.classModel.V2.CourseUserCollection.findOne({ where: { institution_id, user_uuid: userUuid, is_deleted: 0 } });

    // 获取所有标签
    const allTags = await ctx.classModel.V2.CourseTag.findAll({ where: { status: 'online', is_deleted: 0 } });
    const tagList = [];
    for (const v of allTags) {
      tagList[v.id] = v;
    }

    let tags = await ctx.classModel.V2.CourseInstitutionToTag.findAll({ where: { institution_id: institution.id, status: 'online', is_deleted: 0 } });
    tags = _.orderBy(tags, [ 'sort' ], [ 'asc' ]);
    institution.tags = [];
    for (const v of tags) {
      institution.tags.push(tagList[v.tag_id]);
    }

    institution.phone = areas.length > 0 ? areas[0].phone : '';
    institution.distance = areas.length > 0 ? String(areas[0].distance) + 'km' : '无法计算';
    institution.travel_method = areas.length > 0 ? areas[0].travel_method : '';
    institution.travel_tips = areas.length > 0 ? areas[0].travel_tips : '';

    const ret = {
      album,
      detail: institution,
      student_video,
      teachers,
      classes,
      areas,
      is_collected: ctx.isEmpty(userCollect) ? 0 : 1,
    };

    return ret;
  }

  // 处理校区
  async formatArea(area, location) {
    const { ctx, service } = this;
    if (ctx.isEmpty(area)) {
      return {};
    }

    const distance = await service.course.v2.lbs.getDistance({ lng: location.lng, lat: location.lat }, { lng: area.lng, lat: area.lat });
    // 暂定3公里以内步行
    area.travel_method = distance < 3000 ? 'walking' : 'driving';
    const lbsResult = await service.course.v2.lbs.getLBSDistance(area.travel_method, { lng: location.lng, lat: location.lat }, [{ lng: area.lng, lat: area.lat }]);
    if (lbsResult.results.length > 0) {
      area.distance = parseFloat((lbsResult.results[0].distance / 1000).toFixed(1));
      area.duration = lbsResult.results[0].duration;
      const minute = area.travel_method === 'walking' ? Math.ceil(area.distance / 0.08) : Math.ceil(area.duration / 60);
      area.travel_tips = area.travel_method === 'walking' ? `距我${area.distance}km,步行${minute}分钟` : `距我${area.distance}km,开车${minute}分钟`;
    } else {
      area.distance = 999999;
      area.duration = 0;
      area.travel_tips = '';
    }

    return area;
  }

  // 机构列表
  async getInstitutions(input) {
    const { ctx } = this;
    const userUuid = ctx.userUuid;
    const { cat_id, age, address } = input;
    const lat = ctx.isEmpty(input.lat) ? 0 : input.lat;
    const lng = ctx.isEmpty(input.lng) ? 0 : input.lng;

    // 保存定位记录
    if (address && lat && lng) {
      ctx.classModel.V2.CourseLogUserGps.create({ user_uuid: userUuid, address, lat, lng, created_time: moment().format('YYYY-MM-DD HH:mm:ss') });
    }

    let institutionList = [];
    let institutionCats = [];
    const filter = { where: { status: 'online', is_deleted: 0 } };
    // 年龄筛选
    if (Number(age) > 0) {
      filter.where.min_age = { $lte: age };
      filter.where.max_age = { $gte: age };
    }
    // 分类筛选
    if (Number(cat_id) > 0) {
      // 如果是一级分类，则需要加入该分类下所有子分类
      const cats = await ctx.classModel.V2.CourseCat.findAll({ where: { parent_id: cat_id, status: 'online', is_deleted: 0 } });
      const catIds = R.pluck('id', cats);
      catIds.push(Number(cat_id));
      institutionCats = await ctx.classModel.V2.CourseInstitutionToCat.findAll({ where: { status: 'online', is_deleted: 0, cat_id: { $in: catIds } } });
      const institutionIds = R.pluck('institution_id', institutionCats);
      filter.where.id = { $in: institutionIds };
    }

    institutionList = await ctx.classModel.V2.CourseInstitution.findAll(filter);
    institutionList = R.pluck('dataValues', institutionList);


    const ret = await this.formatInstitutionList(institutionList, input);
    return ret;
  }


  // 格式化机构列表
  async formatInstitutionList(institutionList, input) {
    const { ctx, service } = this;
    const userUuid = ctx.userUuid;
    const distance = Number(input.distance) || 0;
    const page = Number(input.page) || 1;
    const limit = Number(input.limit) || 10;
    const { lng, lat } = input;

    let institutionCats = [];
    let institutionIds = R.pluck('id', institutionList);

    // 获取机构对应的校区
    const areaList = await ctx.classModel.V2.CourseArea.findAll({ where: { status: 'online', is_deleted: 0, institution_id: { $in: institutionIds } } });

    // 计算校区对应的距离
    const areaHandle = [];
    for (const v of areaList) {
      areaHandle.push(service.course.v2.lbs.getDistance({ lat, lng }, { lat: v.lat, lng: v.lng }));
    }
    const areaDistanceCalcResult = await Promise.all(areaHandle).then(result => {
      return result;
    }).catch(error => {
      ctx.failed(error);
    });
    for (const i in areaList) {
      areaList[i].distance = areaDistanceCalcResult[i];
    }

    // 选出最短距离的校区
    for (const v of areaList) {
      for (const i in institutionList) {
        if (institutionList[i].id === v.institution_id) {
          if (ctx.isEmpty(institutionList[i].area) || (institutionList[i].area.distance > v.distance)) {
            institutionList[i].area = v;
          }
        }
      }
    }

    // 格式化机构距离
    for (const i in institutionList) {
      institutionList[i].distance = ctx.isEmpty(institutionList[i].area) ? 999999.0 : institutionList[i].area.distance;
    }
    institutionList = _.orderBy(institutionList, [ 'distance' ], [ 'asc' ]);

    // 距离筛选
    if (Number(distance) > 0) {
      for (const i in institutionList) {
        if (institutionList[i].distance > Number(distance)) {
          institutionList = institutionList.slice(0, i);
          break;
        }
      }
    }

    // 分页
    const ret = {
      results: [],
      count: institutionList.length,
    };
    institutionList = institutionList.slice(Number(page - 1) * Number(limit), Number(page) * Number(limit));
    institutionIds = R.pluck('id', institutionList);


    // 获取所有分类
    const allCats = await ctx.classModel.V2.CourseCat.findAll({ where: { status: 'online', is_deleted: 0 } });
    const catList = [];
    for (const v of allCats) {
      catList[v.id] = v;
    }
    institutionCats = await ctx.classModel.V2.CourseInstitutionToCat.findAll({ where: { status: 'online', is_deleted: 0, institution_id: { $in: institutionIds } } });

    // 获取所有标签
    const allTags = await ctx.classModel.V2.CourseTag.findAll({ where: { status: 'online', is_deleted: 0 } });
    const tagList = [];
    for (const v of allTags) {
      tagList[v.id] = v;
    }

    // 用户已收藏机构列表
    const userInstitutions = await ctx.classModel.V2.CourseUserCollection.findAll({ where: { is_deleted: 0, user_uuid: userUuid } });
    const userInstitutionIds = R.pluck('institution_id', userInstitutions);

    // 机构图片及格式化
    for (const i in institutionList) {
      // 格式化机构分类（展示一级分类）
      let cats = [];
      for (const v of institutionCats) {
        if (v.institution_id === institutionList[i].id && catList[v.cat_id]) {
          if (catList[v.cat_id].parent_id === 0) {
            cats.push(v.cat_id);
          } else {
            cats.push(catList[v.cat_id].parent_id);
          }
        }
      }
      // 去重
      cats = _.uniq(cats);
      institutionList[i].cats = [];
      for (const v of cats) {
        institutionList[i].cats.push(catList[v]);
      }

      // 标签
      let tags = await ctx.classModel.V2.CourseInstitutionToTag.findAll({ where: { institution_id: institutionList[i].id, status: 'online', is_deleted: 0 } });
      tags = _.orderBy(tags, [ 'sort' ], [ 'asc' ]);
      institutionList[i].tags = [];
      for (const v of tags) {
        institutionList[i].tags.push(tagList[v.tag_id]);
      }

      // 优先获取机构详情图
      let institutionImages = await ctx.classModel.V2.CourseImages.findAll({ where: { type: 1, type_id: institutionList[i].id, status: 'online', is_deleted: 0 }, order: [[ 'sort', 'asc' ]], limit: 3 });
      if (institutionImages.length < 3) {
        const defaultImages = await ctx.classModel.V2.CourseImages.findAll({ where: { type: 4, type_id: { $in: cats }, status: 'online', is_deleted: 0 }, limit: 3 - institutionImages.length });
        institutionImages = institutionImages.concat(defaultImages);
      }
      institutionList[i].images = institutionImages;

      institutionList[i].distance = String((institutionList[i].distance / 1000).toFixed(1)) + 'km';
      institutionList[i].phone = institutionList[i].area.length > 0 ? institutionList[i].area[0].phone : '';

      // 是否已收藏
      institutionList[i].is_collected = userInstitutionIds.includes(institutionList[i].id) ? 1 : 0;
      ret.results.push(institutionList[i]);
    }

    return ret;
  }


  // 搜索
  async search(input) {
    const { ctx } = this;
    const { cat_id, age, search } = input;
    const userUuid = ctx.userUuid;

    // 保存搜索记录
    if (search) {
      const searchInfo = await ctx.classModel.V2.CourseSearch.findOne({ where: { content: search, is_deleted: 0 } });
      if (searchInfo) {
        await ctx.classModel.V2.CourseSearch.update({ count: searchInfo.count + 1 }, { where: { id: searchInfo.id } });
      } else {
        await ctx.classModel.V2.CourseSearch.create({ content: search, sort: 0, count: 1, is_hot: 0, status: 'online', is_deleted: 0, created_time: moment().format('YYYY-MM-DD HH:mm:ss'), updated_time: moment().format('YYYY-MM-DD HH:mm:ss') });
      }

      await ctx.classModel.V2.CourseUserSearch.create({ user_uuid: userUuid, content: search, status: 'online', created_time: moment().format('YYYY-MM-DD HH:mm:ss'), updated_time: moment().format('YYYY-MM-DD HH:mm:ss') });
    }

    let institutionList = [];
    let institutionCats = [];
    let institutionIds = [];
    const filter = { where: { status: 'online', is_deleted: 0 }, row: true };

    const classFilter = { where: { status: 'online', is_deleted: 0, name: { $like: '%' + search + '%' } }, attributes: [ 'id', 'institution_id', 'name', 'status', 'is_deleted' ], row: true };
    // 年龄筛选
    if (Number(age) > 0) {
      filter.where.min_age = { $lte: age };
      filter.where.max_age = { $gte: age };
    }
    // 分类筛选
    if (Number(cat_id) > 0) {
      // 如果是一级分类，则需要加入该分类下所有子分类
      const cats = await ctx.classModel.V2.CourseCat.findAll({ where: { parent_id: cat_id, status: 'online', is_deleted: 0 } });
      const catIds = R.pluck('id', cats);
      catIds.push(Number(cat_id));
      institutionCats = await ctx.classModel.V2.CourseInstitutionToCat.findAll({ where: { status: 'online', is_deleted: 0, cat_id: { $in: catIds } } });
      institutionIds = R.pluck('institution_id', institutionCats);
    }

    if (institutionIds.length > 0) {
      filter.where.id = { $in: institutionIds };
      classFilter.where.institution_id = { $in: institutionIds };
    }
    const institutionFilter = filter;
    institutionFilter.where.name = { $like: '%' + search + '%' };
    institutionList = await ctx.classModel.V2.CourseInstitution.findAll(institutionFilter);
    const ids = R.pluck('id', institutionList);

    // 课程搜索
    const classList = await ctx.classModel.V2.CourseClass.findAll(classFilter);
    // 去除已经搜到的机构
    const classInstitutionIds = _.difference(R.pluck('institution_id', classList), ids);
    if (classInstitutionIds.length > 0) {
      filter.where.id = { $in: classInstitutionIds };
      const classInstitutionList = await ctx.classModel.V2.CourseInstitution.findAll(filter);
      institutionList = institutionList.concat(classInstitutionList);
    }

    institutionList = R.pluck('dataValues', institutionList);
    const ret = await this.formatInstitutionList(institutionList, input);
    return ret;
  }


  // 获取热搜
  async getHotSearch() {
    const { ctx } = this;
    const search = await ctx.classModel.V2.CourseSearch.findAll({ where: { status: 'online', is_deleted: 0, is_hot: 1 }, order: [[ 'sort', 'asc' ]] });

    const ret = {
      results: R.pluck('content', search),
      count: search.length,
    };

    return ret;
  }


  // 获取用户搜索历史
  async getUserSearch() {
    const { ctx } = this;
    const userUuid = ctx.userUuid;
    const search = await ctx.classModel.V2.CourseUserSearch.findAll({ where: { status: 'online', user_uuid: userUuid }, limit: 10, order: [[ 'id', 'desc' ]] });
    const result = _.uniq(R.pluck('content', search));

    const ret = {
      results: result,
      count: result.length,
    };

    return ret;
  }


  // 删除用户搜索历史
  async deleteUserSearch() {
    const { ctx } = this;
    const userUuid = ctx.userUuid;
    await ctx.classModel.V2.CourseUserSearch.update({ status: 'offline' }, { where: { user_uuid: userUuid, status: 'online' } });
    return;
  }


  // 评论列表
  async getComments(input) {
    const { ctx } = this;
    const page = Number(input.page) || 1;
    const limit = Number(input.limit) || 10;
    const offset = (page - 1) * limit;
    const institution_id = Number(input.institution_id) || 0;

    const comments = await ctx.classModel.V2.CourseComment.findAndCountAll({ where: { institution_id, status: 'online', is_deleted: 0 }, offset, limit, order: [[ 'id', 'desc' ]] });
    comments.rows = R.pluck('dataValues', comments.rows);

    const ret = {
      results: await this.formatComments(comments.rows),
      count: comments.count,
    };

    return ret;
  }

  // 格式化评论列表
  async formatComments(comments) {
    const { ctx } = this;
    if (ctx.isEmpty(comments)) {
      return [];
    }

    const ids = R.pluck('id', comments);
    const images = await ctx.classModel.V2.CourseImages.findAll({ where: { type: 3, type_id: { $in: ids }, status: 'online', is_deleted: 0 } });

    const ret = [];
    for (const v of comments) {
      // 评论图片
      let commentImages = [];
      for (const j of images) {
        if (j.type_id === v.id) {
          commentImages.push(j);
        }
      }
      commentImages = _.orderBy(commentImages, [ 'sort' ], [ 'asc' ]);

      ret.push({
        id: v.id,
        institution_id: v.institution_id,
        user_uuid: v.user_uuid,
        nickname: v.nickname,
        avatar: v.avatar,
        content: v.content,
        has_image: v.has_image,
        images: commentImages,
        created_time: v.created_time,
      });
    }

    return ret;
  }


  // 搜索关联
  async getSuggestSearch(input) {
    const { ctx } = this;
    const { search } = input;
    let results = [];
    if (!ctx.isEmpty(search)) {
      const institutions = await ctx.classModel.V2.CourseInstitution.findAll({ where: { status: 'online', is_deleted: 0, name: { $like: '%' + search + '%' } }, limit: 10, attributes: [ 'id', 'name', 'status', 'is_deleted' ] });
      results = R.pluck('name', institutions);
    }

    const ret = {
      results,
      count: results.length,
    };

    return ret;
  }


  // 教师详情
  async getTeacher(id) {
    const { ctx } = this;
    let teacher = await ctx.classModel.V2.CourseTeacher.findOne({ where: { id, status: 'online', is_deleted: 0 } });
    if (ctx.isEmpty(teacher)) {
      ctx.failed('数据不存在');
    }

    teacher = teacher.dataValues;
    teacher.point_tags = teacher.point ? teacher.point.split(',') : [];
    teacher.work_experience_tags = teacher.work_experience ? teacher.work_experience.split(';') : [];

    const institution = await ctx.classModel.V2.CourseInstitution.findOne({ where: { id: teacher.institution_id } });
    teacher.institution_name = institution.name;

    return teacher;
  }


  // 教师列表
  async getTeachers(input) {
    const { ctx } = this;
    const page = Number(input.page) || 1;
    const limit = Number(input.limit) || 10;
    const offset = (page - 1) * limit;
    const institutionId = Number(input.institution_id) || 0;
    const teachers = await ctx.classModel.V2.CourseTeacher.findAndCountAll({ where: { institution_id: institutionId, status: 'online', is_deleted: 0 }, raw: true, offset, limit });

    const ret = {
      results: teachers.rows,
      count: teachers.count,
    };
    return ret;
  }


  // 课程列表
  async getClasses(input) {
    const { ctx } = this;
    const page = Number(input.page) || 1;
    const limit = Number(input.limit) || 10;
    const offset = (page - 1) * limit;
    const institutionId = Number(input.institution_id) || 0;
    const attributes = [ 'id', 'institution_id', 'name', 'type', 'price', 'status', 'is_deleted' ];
    const classes = await ctx.classModel.V2.CourseClass.findAndCountAll({ where: { institution_id: institutionId, status: 'online', is_deleted: 0 }, raw: true, offset, limit, attributes });
    const classIds = R.pluck('id', classes.rows);

    // 课程图片
    const classImages = await ctx.classModel.V2.CourseImages.findAll({ where: { type: 2, type_id: { $in: classIds }, status: 'online', is_deleted: 0 }, raw: true });
    for (const i in classes.rows) {
      let images = [];
      for (const v of classImages) {
        if (v.type_id === classes.rows[i].id) {
          images.push(v);
        }
      }
      images = _.orderBy(images, [ 'sort' ], [ 'asc' ]);
      classes.rows[i].image = images.length > 0 ? images[0] : {};
    }

    const ret = {
      results: classes.rows,
      count: classes.count,
    };
    return ret;
  }


  // 课程详情
  async getClass(id) {
    const { ctx } = this;
    const classInfo = await ctx.classModel.V2.CourseClass.findOne({ where: { id, status: 'online', is_deleted: 0 }, raw: true });
    if (ctx.isEmpty(classInfo)) {
      ctx.failed('数据不存在');
    }

    // 课程图片
    let images = await ctx.classModel.V2.CourseImages.findAll({ where: { type: 2, type_id: id, status: 'online', is_deleted: 0 }, raw: true });
    // 去重
    images = _.uniqBy(images, function(v) { return (v.is_image === 1 ? v.image_url : v.video_url); });
    images = _.orderBy(images, [ 'sort' ], [ 'asc' ]);

    classInfo.images = images;
    return classInfo;
  }


  // 用户收藏机构列表
  async getUserCollectedInstitutions(input) {
    const { ctx } = this;
    const userUuid = ctx.userUuid;

    const userCollection = await ctx.classModel.V2.CourseUserCollection.findAll({ where: { user_uuid: userUuid, is_deleted: 0 }, raw: true });
    const institutionIds = R.pluck('institution_id', userCollection);
    const institutionList = await ctx.classModel.V2.CourseInstitution.findAll({ where: { id: { $in: institutionIds }, status: 'online', is_deleted: 0 }, raw: true });

    const ret = await this.formatInstitutionList(institutionList, input);
    return ret;
  }
}

module.exports = InstitutionSubService;
