# coding:utf-8
"""导出对应用户的优质日记本(评分4分及以上),以及相应的图片下载。"""

import os
import os.path
import time
from collections import OrderedDict

from django.core.management.base import BaseCommand, CommandError

from utils.execel import ExcelReader, ExcelWriter
from talos.libs.img_download import IMGDownloader
from gm_types.gaia import TOPIC_IMAGE_TYPE
from talos.libs.image_utils import get_temp_image_path
from talos.libs.image_utils import get_full_path
from talos.models.diary import Diary
from talos.models.topic import Problem, TopicImage
from talos.models.diary.preoperationimage import PreOperationImage
from django.db.models import Q


BASESAVE_DIR = "export_result"
AFTER  ='after'
BEFORE = 'before'


class Command(BaseCommand):
    help = '导出对应用户的优质日记本,以及相应的图片下载。'

    def add_arguments(self, parser):

        # 添加 excel 绝对路径
        parser.add_argument(
            '-f', '--excel', type=str,
            dest='users_excel',
            help='用户ID文件'
        )

        # 结果保存路径,保存在对应的路径下面的 export_result 目录下面
        parser.add_argument(
            '-p', '--save-path', type=str,
            dest='export_path',
            help='结果保存路径',
            default='.'
        )

    def handle(self, *args, **options):

        print('------ starting -----')
        start_time = time.time()
        print("start at: ", start_time)

        user_id_file = options.get("users_excel", None)
        if not user_id_file:
            raise CommandError("请指定用户ID文件")

        reader = ExcelReader(user_id_file)
        users_id = reader.read_column(2)  # 规定第二列为用户ID

        if len(users_id) <= 1:
            raise CommandError("请确保文件格式为规定的格式")

        users_id = users_id[1:]

        # users_id 第一个为标题
        if not all(map(lambda i: isinstance(i, int), users_id)):
            raise CommandError("用户列表存在不合法id(全部为数字)")

        # 创建结果存放路径
        export_path = options.get("export_path")
        result_path = os.path.join(export_path, BASESAVE_DIR)
        mkdirp(result_path)

        # 获取用户优质日记本
        diaries = get_user_diaries(users_id)
        diaries_id = []
        [diaries_id.extend(i) for i in diaries.values()]

        before_operation_images = get_diary_img(diaries_id, TOPIC_IMAGE_TYPE.PRE_OPERATION_IMAGE)  # 术前
        after_operation_images = get_diary_img(diaries_id, TOPIC_IMAGE_TYPE.POST_OPERATION_IMAGE)  # 术后

        result_excel = os.path.join(result_path, "用户日记本链接地址.xlsx")
        excel = ExcelWriter(result_excel)
        excel.write_header(["用户ID", "用户日记本地址"])

        rows = []
        for user_id, diaries_id in diaries.items():
            rows.append([user_id, "\n".join(get_diaries_link(diaries_id))])

            for diary_id in diaries_id:

                # 创建日记本、术前、术后图片目录
                diary_path = os.path.join(result_path,
                                          "用户{user_id}".format(user_id=user_id),
                                          str(diary_id))
                after_path = os.path.join(diary_path, AFTER)
                before_path = os.path.join(diary_path, BEFORE)
                mkdirp(after_path)
                mkdirp(before_path)

                for d_id, imgs in after_operation_images.items():
                    if diary_id == d_id:
                        IMGDownloader.download(imgs, after_path)

                for d_id, imgs in before_operation_images.items():
                    if diary_id == d_id:
                        IMGDownloader.download(imgs, before_path)

        excel.write_rows(2, rows)
        excel.save()

        end_time = time.time()
        print("end at: ", end_time)
        print('total use {} s.'.format(end_time - start_time))
        print('Done!')


def mkdirp(des):
    if not os.path.exists(des):
        os.makedirs(des, exist_ok=True)


def get_user_diaries(users_id):
    """获取用户日记本。

    {
        user_id: [ diary_id, ]
    }
    """

    diaries = Diary.objects.filter(Q(user_id__in=users_id) &
                                   Q(content_level__in=('4', '5'))).values("user_id", "id").iterator()

    res = OrderedDict()
    for user_id in users_id:
        res[user_id] = []

    for diary in diaries:
        res[diary["user_id"]].append(diary["id"])

    return res


def get_diary_img(diary_ids, img_type, watermark=True):
    """获取日记本图片。

    :param diary_ids: 日记本id list
    :param img_type: 图片类型:0术前, 1术后
    :param img_num: 一次最多获取的日记本img_num
    :param watermark: 是否加水印
    :return:
    {
        diary_id: [img_url],
    }
    """
    if img_type == TOPIC_IMAGE_TYPE.PRE_OPERATION_IMAGE:  # 术前图片
        images = PreOperationImage.objects.filter(
            diary_id__in=diary_ids
        ).values('diary_id', 'image_url').iterator()

        result = {}
        for img in images:
            if img["diary_id"] not in result:
                result[img["diary_id"]] = []
            result[img["diary_id"]].append(img["image_url"])
    else:
        topics = Problem.objects.filter(
            diary_id__in=diary_ids, is_online=True
        ).values('id', "diary_id").iterator()

        res = {}  # key: diary_id value: topic_id list
        topic_ids = []
        for topic in topics:
            topic_ids.append(topic["id"])

            if topic["diary_id"] not in res:
                res[topic["diary_id"]] = []

            res[topic["diary_id"]].append(topic["id"])

        images = TopicImage.objects.filter(topic_id__in=topic_ids).order_by(
            '-taken_time'
        ).values('image_url', 'topic_id')

        result = {}  # key: diary_id value: image_url list
        for diary_id, topics in res.items():
            if diary_id not in result:
                result[diary_id] = []

            for topic_id in topics:
                for img in images:
                    if img["topic_id"] == topic_id:
                        result[diary_id].append(img["image_url"])

    res = {}
    for diary_id, image_urls in result.items():
        res[diary_id] = []
        for url in image_urls:
            image_url = get_full_path(url, '-w') if watermark else get_temp_image_path(url)
            res[diary_id].append(image_url)

    return res


def get_diaries_link(diaries_id):
    """获取m站日记本链接"""

    return [
        "http://m.igengmei.com/diary_book/{diary_id}/".format(diary_id=diary_id)
        for diary_id in diaries_id
    ]