package reporter

import (
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"time"

	"hnyfkj.com.cn/rtu/linux/baseapp"
	camera1 "hnyfkj.com.cn/rtu/linux/mvs_u_takephoto"
	"hnyfkj.com.cn/rtu/linux/utils/ftpclient"
	mcu "hnyfkj.com.cn/rtu/xy_v/mcu_ctrl_board"
)

const (
	PhotoTimeout = 5 * 60 // 拍照超时时间, 单位: 秒
)

func (r *MQTTReporter) loopTakePhoto() {
	for {
		select {
		case <-mcu.Board.ReqTakePhoCh:
			r.takePhotoAndUpToFtp()
		case <-r.ctx.Done():
			return
		} // end select
	} // end for
}

func (r *MQTTReporter) takePhotoAndUpToFtp() (string, error) {
	// 1, 开始执行拍照任务
	mcu.GlobalWorkState.Add(mcu.PhotoCapturing)
	baseapp.Logger.Infof("[%s] 拍照中, 稍后...", MODULE_NAME)

	r.pruneOldPhotos(baseapp.IMG_DIR, 1000) // 清理旧照片(避免磁盘空间不足), 只保留最新的1000张

	now := time.Now()
	imgFile := filepath.Join(baseapp.IMG_DIR, fmt.Sprintf("%s.jpg", now.Format("2006-01-02_15-04-05.000")))
	_, err := camera1.TakePhoto(camera1.IMG_TYPE_JPG, imgFile, PhotoTimeout)
	if err != nil {
		baseapp.Logger.Errorf("[%s] 拍照失败: %v!!", MODULE_NAME, err)
		mcu.GlobalWorkState.Remove(mcu.PhotoCapturing)
		return "", err
	}
	elapsed := time.Since(now).Milliseconds()
	baseapp.Logger.Infof("[%s] 拍照完成, 输出到本地文件: %q, 用时: %d毫秒", MODULE_NAME, imgFile, elapsed)
	mcu.GlobalWorkState.Remove(mcu.PhotoCapturing)

	// 2, 上传照片到服务器
	ftpclient.FileUploader.Lock() // 上传锁定(多个上传任务并发时, 保证串行执行)
	defer ftpclient.FileUploader.Unlock()

	mcu.GlobalWorkState.Add(mcu.PhotoUploading)
	now = time.Now()
	baseapp.Logger.Infof("[%s] 正在上传照片文件%q到服务器...", MODULE_NAME, imgFile)

	remoteFile, err := ftpclient.UploadFileToFtp(r.ctx, imgFile, CfgServers.Img2Ftp.Address, CfgServers.Img2Ftp.Username, CfgServers.Img2Ftp.Password, ftpclient.DefaultUploadTimeout)
	if err != nil {
		baseapp.Logger.Errorf("[%s] 照片文件%q上传失败: %v!!", MODULE_NAME, imgFile, err)
		mcu.GlobalWorkState.Remove(mcu.PhotoUploading)
	} else {
		os.Remove(imgFile)
		elapsed = time.Since(now).Milliseconds()
		baseapp.Logger.Infof("[%s] 照片文件上传成功, 用时: %d毫秒, 本地文件: %q已删除", MODULE_NAME, elapsed, imgFile)
		mcu.GlobalWorkState.Remove(mcu.PhotoUploading)
	}

	return remoteFile, err
}

func (r *MQTTReporter) pruneOldPhotos(dir string, maxCount int) error {
	files, err := os.ReadDir(dir)
	if err != nil {
		return err
	}

	type fileInfo struct {
		name    string
		path    string
		modTime time.Time
	}
	var jpgFiles []fileInfo

	for _, f := range files { // 遍历目录, 找出所有jpg文件
		if !f.IsDir() && filepath.Ext(f.Name()) != ".jpg" {
			continue
		}
		info, err := f.Info()
		if err != nil {
			continue
		}
		jpgFiles = append(jpgFiles, fileInfo{name: f.Name(), path: filepath.Join(dir, f.Name()), modTime: info.ModTime()})
	}

	if len(jpgFiles) <= maxCount {
		return nil
	}

	sort.Slice(jpgFiles, func(i, j int) bool {
		if jpgFiles[i].modTime.Equal(jpgFiles[j].modTime) {
			return jpgFiles[i].name < jpgFiles[j].name // 如果时间相同, 则按文件名排序
		}
		return jpgFiles[i].modTime.Before(jpgFiles[j].modTime) // 默认按照文件的修改时间排序
	})

	for i := 0; i < len(jpgFiles)-maxCount; i++ {
		os.Remove(jpgFiles[i].path)
	}

	return nil
}
