#!/usr/bin/env python
# -*- coding: utf_8 -*-

import os
import copy
import time
import types
import json
import shutil
import logging
import traceback
from urllib.parse import urlparse, urljoin
from datetime import datetime
from pony.orm import *
from flask import request
from app.setting import config
from model import fullStackDB
from model.apps import Apps
from model.annex import Annex
from model.build_logs import BuildLogs
from model.user import User
from utils import sql_filter
from utils.tools_epk import EpkApp

logger = logging.getLogger("BuildLogsManager")

class BuildLogsManager(object):
    def __init__(self):
        super(BuildLogsManager, self).__init__()

    def add(self, app):
        with db_session:
            editor = User.get(id=request.current_user.get("id"))
            if not editor:
                return False, "current user is not exists"

            # 根据app查询应用,获取应用有哪些文件
            # 按格式创建文件夹,将这些文件移动到这个文件夹
            # 将这些零散文件进行打包
            # 更新数据库对应文件的路径

            app = Apps.get(uuid=app)
            if not app:
                return None, "app not found"

            source_files = Annex.select().filter(app=app)
            if not source_files:
                return None, "apps file not found"

            dir_format = "{}-{}-{}".format(app.app_name, app.app_version, datetime.now().strftime("%Y%m%d%H%M%S"))
            upload_dir = os.sep.join([config.get("UPLOAD_PATH"), config.get("UPLOAD_DIR"), "evueapps"])
            target_dir = os.sep.join([upload_dir, editor.account, dir_format])
            dest_dir = os.sep.join([target_dir, "src"])
            if not os.path.exists(dest_dir):
                os.makedirs(dest_dir)

            app_files = []
            for sf in source_files:
                parsed_result = urlparse(sf.path)
                target_file = os.sep.join([config.get("UPLOAD_PATH"), parsed_result.path.replace('\\', '/')])
                shutil.move(os.path.normpath(target_file), os.path.normpath(dest_dir))
                app_files.append([sf.id, os.sep.join([dest_dir, os.path.basename(parsed_result.path)])])
                # if os.path.exists(target_file):
                #     shutil.move(target_file, dest_dir)
                #     app_files.append([sf.id, os.sep.join([dest_dir, os.path.basename(parsed_result.path)])])
                # else:
                #     print("file not found: %s" % target_file)
                #     break

            try:
                # 打包成EPK文件
                epk = EpkApp(appName=dir_format, appDir=dest_dir, appVersion=app.app_version, output=target_dir)
                app_info = epk.pack()
            except Exception as e:
                logger.error(e)
                traceback.print_exc()

            # 更新数据库对应文件路径
            for sf in source_files:
                for af in app_files:
                    if sf.id == af[0]:
                        t = os.path.normpath(af[1].replace(config.get("UPLOAD_PATH"), "")).replace('\\', '/')
                        sf.set(path=urljoin(config.get("UPLOAD_SERVER"), t))
                        flush()
            commit()

            epk_path = os.sep.join([target_dir.replace(config.get("UPLOAD_PATH"), ""), "{}.epk".format(dir_format)])
            epk_path = urljoin(config.get("UPLOAD_SERVER"), epk_path.replace('\\', '/'))

            app_info['md5'] = str(app_info['md5'])
            result = BuildLogs(app=app, app_path=epk_path, app_info=app_info, create_by=editor, create_at=datetime.now(), update_by=editor, update_at=datetime.now())
            commit()

            return epk_path, "add build_logs {}.".format("success" if result else "fail")

    def delete(self, uuid):
        editor = User.get(id=request.current_user.get("id"))
        if not editor:
            return False, "current user is not exists"

        result = fullStackDB.update(BuildLogs, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
        return result, "delete build_logs {}.".format("success" if result else "fail")

    def get(self, data):
        result = BuildLogs.get(**data)
        if result:
            result = result.to_dict(only=["uuid", "name", "create_at", "update_at"])
        return result, "get build_logs {}.".format("success" if result else "no data")

    def getList(self, data):
        if not data or len(data) <= 0:
            return False, 0, "parameters can not be null."

        temp = copy.deepcopy(data)
        if 'pagenum' in temp:
            temp.pop('pagenum')
        if 'pagesize' in temp:
            temp.pop('pagesize')
        if 'scope_type' in temp:
            temp.pop('scope_type')
        temp.setdefault("is_delete", False)

        if "scope_type" in data and data.get("scope_type") == "list":
            result = BuildLogs.select().where(**temp).order_by(desc(BuildLogs.create_at))
            temp = []
            for item in result:
                temp.append(item.to_dict(only=["uuid"]))
            return temp, len(temp), "get build_logs {}.".format("success" if temp else "fail")

        result = fullStackDB.pagination(BuildLogs, BuildLogs.create_at, pagenum=data.get("pagenum", 1), pagesize=data.get("pagesize", 10), **temp)
        count = fullStackDB.count(BuildLogs, **temp)

        if result and len(result):
            temp = []
            for item in result:
                t = item.to_dict(with_collections=True, related_objects=True, exclude=["is_delete", "delete_by", "delete_at"])
                t.update({
                    "app": item.app.to_dict(exclude=["is_delete", "delete_by", "delete_at"]),
                    "create_by": item.create_by.to_dict(only=["uuid", "username"]),
                    "update_by": item.update_by.to_dict(only=["uuid", "username"]),
                    "create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S") if item.create_at else None,
                    "update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S") if item.update_at else None,
                })
                temp.append(t)
            result = temp

        return result, count, "get build_logs {}.".format("success" if result else "no data")

    def update(self, uuid, data):
        # 当参数为空时,直接返回错误
        if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
            return False, "parameters can not be null."

        # 查询请求者是否存在
        editor = User.get(id=request.current_user.get("id"))
        if not editor:
            return False, "current user is not exists"

        result = fullStackDB.update(BuildLogs, { 'uuid': uuid }, update_at=datetime.now(), update_by=editor, **data)
        return result, "update permission {}.".format("success" if result else "fail")

buildLogsManager = BuildLogsManager()