package financial

import (
	"context"
	"errors"
	"fmt"
	"mime/multipart"
	"path"
	"strings"
	"time"

	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/business/jxutils"
	"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
	"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
	"git.rosy.net.cn/jx-callback/business/jxutils/weixinmsg"
	"git.rosy.net.cn/jx-callback/business/model/dao"
	"git.rosy.net.cn/jx-callback/business/model/legacymodel"
	"git.rosy.net.cn/jx-callback/globals"
	"git.rosy.net.cn/jx-callback/globals/api"
	"github.com/qiniu/api.v7/storage"
)

type tUploadFileInfo struct {
	FileHeader *multipart.FileHeader
	StoreID    int
}

func SendFilesToStores(ctx *jxcontext.Context, files []*multipart.FileHeader, title, shopName string, isAsync bool, userName string) (hint string, err error) {
	if len(files) == 0 {
		return "", errors.New("没有文件上传！")
	}

	fileList := make([]*tUploadFileInfo, len(files))
	for k, fileHeader := range files {
		fileList[k] = &tUploadFileInfo{
			FileHeader: fileHeader,
		}
		fileNameParts := strings.Split(fileHeader.Filename, "_")
		if len(fileNameParts) < 3 {
			return "", fmt.Errorf("文件名:%s不规范，没有包含三个必要的部分", fileHeader.Filename)
		}
		fileList[k].StoreID = int(utils.Str2Int64WithDefault(fileNameParts[0], 0))
		// 果园和菜市账号冲突,果园门店ID调整变大
		//if fileList[k].StoreID < 100000 || fileList[k].StoreID > 1000000 {
		//	return "", fmt.Errorf("文件名:%s不规范，不以合法的京西门店ID开始", fileHeader.Filename)
		//}
	}
	putPolicy := storage.PutPolicy{
		Scope:   globals.QiniuBucket,
		Expires: 10 * 60,
	}
	upToken := putPolicy.UploadToken(api.QiniuAPI)
	cfg := &storage.Config{}
	task := tasksch.NewParallelTask("SendFilesToStores", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
		func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
			fileInfo := batchItemList[0].(*tUploadFileInfo)
			fileHeader := fileInfo.FileHeader
			db := dao.GetDB()
			storeID, _ := dao.GetRealLinkStoreID(db, fileInfo.StoreID)
			storeDetail, _ := dao.GetStoreDetail(db, storeID, 0, "")
			if storeDetail != nil && storeDetail.PushBill == 1 {
				return retVal, err
			}
			file, err := fileHeader.Open()
			if err == nil {
				ret := storage.PutRet{}
				key := "storeBill/" + utils.Int2Str(storeID) + "_" + strings.ToLower(utils.GetUUID()) + path.Ext(fileHeader.Filename)
				formUploader := storage.NewFormUploader(cfg)
				for i := 0; i < 3; i++ {
					if err = formUploader.Put(context.Background(), &ret, upToken, key, file, fileHeader.Size, &storage.PutExtra{}); err == nil {
						break
					}
				}
				file.Close()
				if err == nil {
					billRec := &legacymodel.StoreBill{
						Date:      time.Now(),
						Url:       strings.Replace(jxutils.ComposeQiniuResURL(ret.Key), "http://", "https://", -1),
						StoreId:   storeID,
						BillName:  fileHeader.Filename,
						ShopName:  shopName,
						BillTitle: title,
					}
					if err = dao.CreateEntity(db, billRec); err == nil {
						err = weixinmsg.NotifySaleBill(storeID, title, shopName, fmt.Sprintf("%s/billshow/?path=%s", globals.BackstageHost, billRec.Url))
						if err != nil {
							globals.SugarLogger.Infof("SendFilesToStores NotifySaleBill file:%s error:%v", fileHeader.Filename, err)
						}
						err = nil // 忽略微信发送错误
					} else {
						globals.SugarLogger.Warnf("SendFilesToStores CreateEntity file:%s error:%v", fileHeader.Filename, err)
					}
				} else {
					globals.SugarLogger.Warnf("SendFilesToStores file:%s failed with error:%v", fileHeader.Filename, err)
				}
			} else {
				globals.SugarLogger.Warnf("SendFilesToStores open file:%s failed with error:%v", fileHeader.Filename, err)
			}
			return retVal, err
		}, fileList)
	tasksch.HandleTask(task, nil, true).Run()
	hint = task.ID
	if !isAsync {
		_, err = task.GetResult(0)
	}
	return task.ID, err
}

func GetStoreBills(ctx *jxcontext.Context, storeID int) (bills []*legacymodel.StoreBill, err error) {
	db := dao.GetDB()
	if err = dao.GetRows(db, &bills, `
	SELECT *
	FROM store_bill
	WHERE store_id = ?
	ORDER BY date DESC
	LIMIT 10
	`, storeID); err != nil {
		return nil, err
	}
	return bills, err
}
