package admin

import (
	"errors"
	"fmt"
	"github.com/kataras/iris/v12"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
	"main/config"
	"main/database"
	"main/model"
	"main/utils"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
)

var ipLocationList []model.IpsLocation

func getLogStats(ctx iris.Context) {
	var logStats []resLogStats
	db := database.GetInstance().GetMysqlDb()
	if err := db.Model(&model.Logs{}).Select("left(time, 10) name", "count(1) value").Order("left(time,10)").Group("left(time,10)").Scan(&logStats).Error; err != nil {
		logrus.Errorln("sql执行失败：", err)
	}
	err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", logStats))
	if utils.ErrHandle(ctx, err) {
		return
	}
}

func getLogDetail(ctx iris.Context) {
	var logs []model.Logs
	date := ctx.URLParam("date")
	db := database.GetInstance().GetMysqlDb()
	if err := db.Where("left(time,10) = ?", date).Find(&logs).Error; err != nil {
		logrus.Errorln("sql执行失败：", err)
	}
	err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", logs))
	if utils.ErrHandle(ctx, err) {
		return
	}
}

func getSysLogs(ctx iris.Context) {
	var logs []model.SysLogs
	var resLogs []model.SysLogs
	startTime := ctx.URLParam("start_time")
	endTime := ctx.URLParam("end_time")
	containerName := ctx.URLParam("container_name")
	message := ctx.URLParam("message")
	db := database.GetInstance().GetMysqlDb()
	//生成子查询
	query := db.Model(&model.SysLogs{})
	if startTime == "" {
		startTime = time.Date(2000, 0, 1, 0, 0, 0, 0, time.Local).Format("2006-01-02 15:04:05")
	}
	if endTime == "" {
		endTime = time.Now().Format("2006-01-02 15:04:05")
	}
	query.Where("time >= ? and time <= ?", startTime, endTime)
	if containerName != "" {
		query.Where("container_name = ?", containerName)
	}
	//查询，限制1000条日志
	if err := query.Order("time desc").Limit(1000).Find(&logs).Error; err != nil {
		ctx.StatusCode(iris.StatusInternalServerError)
		ctx.SetErr(errors.New("系统错误，请联系管理员"))
		logrus.Errorln("查询容器日志sql失败：", err, "查询参数：", startTime, endTime, containerName)
		return
	}
	//过滤包含message内容
	if message != "" {
		for _, log := range logs {
			if strings.Contains(log.Message, message) {
				resLogs = append(resLogs, log)
			}
		}
		err := ctx.JSON(utils.FormatRes(iris.StatusOK, strconv.Itoa(len(resLogs)), resLogs))
		if err != nil {
			return
		}
	} else {
		err := ctx.JSON(utils.FormatRes(iris.StatusOK, strconv.Itoa(len(logs)), logs))
		if err != nil {
			return
		}
	}
}

// 获取日志容器名称列表
func getSysLogsContainerList(ctx iris.Context) {
	var list []string
	db := database.GetInstance().GetMysqlDb()
	if err := db.Model(&model.SysLogs{}).Distinct("container_name").Find(&list).Error; err != nil {
		logrus.Errorln("sql执行失败：", err)
	}
	err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", list))
	if err != nil {
		return
	}
}

// 手动保存日志
func saveLogs(ctx iris.Context) {
	cPath, _ := os.Getwd()
	logPath := path.Join(path.Join(cPath, config.Config.Logs.Nginx))
	fileList, err := os.ReadDir(logPath)
	if utils.ErrHandle(ctx, err) {
		return
	}
	var resLogList []model.Logs
	var logDealList []model.LogFileDealLog
	db := database.GetInstance().GetMysqlDb()
	if err1 := db.Find(&logDealList).Error; err1 != nil {
		logrus.Errorln("sql执行失败：", err1)
	}
	for _, file := range fileList {
		if strings.Contains(file.Name(), "access-") {
			date := strings.Split(strings.Split(file.Name(), "access-")[1], ".")[0]
			if checkDate(date, logDealList) {
				continue
			}
			if err1 := db.Where("time like ?", fmt.Sprintf("%s%%", date)).Delete(&resLogList).Error; err1 != nil {
				logrus.Errorln("sql执行失败：", err1)
			}
			logList, err := utils.FileRead(path.Join(logPath, file.Name()), true)
			if utils.ErrHandle(ctx, err) {
				return
			}
			for _, v := range logList {
				c := make(chan model.Logs)
				go FormatLog(v, date, c)
				resLogItem := <-c
				if err1 := db.Create(&resLogItem).Error; err1 != nil {
					logrus.Errorln("sql执行失败：", err1)
				}
				resLogList = append(resLogList, resLogItem)
			}
			if err1 := db.Create(&model.LogFileDealLog{
				Date:    date,
				Success: true,
			}).Error; err1 != nil {
				logrus.Errorln("sql执行失败：", err1)
			}
		}
	}
	err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", resLogList))
	if utils.ErrHandle(ctx, err) {
		return
	}
}

// 判断日期是否已处理
func checkDate(date string, list []model.LogFileDealLog) bool {
	for _, v := range list {
		if v.Date == date && v.Success {
			return true
		}
	}
	return false
}

// 格式化日志内时间格式
func formatTime(date string, s string) string {
	l := strings.Split(s, ":")
	return fmt.Sprintf("%s %s:%s:%s", date, l[1], l[2], l[3])
}

// 从本地ipLocationList记录中获取IP对应地址
func getLocalIpAddr(ip string) string {
	for _, v := range ipLocationList {
		if v.Ip == ip {
			return v.Location
		}
	}
	return ""
}

// 从接口中获取IP对应地址
func getIpAddr(ip string) (string, error) {
	db := database.GetInstance().GetMysqlDb()
	location, err := utils.GetIpLocation(ip)
	if err != nil {
		return "", err
	}
	ipItem := model.IpsLocation{
		Ip:       ip,
		Location: location,
		Model:    gorm.Model{},
	}
	if err1 := db.Create(&ipItem).Error; err1 != nil {
		logrus.Errorln("sql执行失败：", err1)
	}
	UpdateLocalIpList()
	return location, nil
}
