package system

import (
	"fmt"
	"net/http"
	"net/url"
	"sync"
	"time"

	"kra/internal/biz/system"
	"kra/pkg/response"
	"kra/pkg/utils"

	"github.com/gin-gonic/gin"
)

// 用于token一次性存储
var (
	exportTokenCache      = make(map[string]interface{})
	exportTokenExpiration = make(map[string]time.Time)
	tokenMutex            sync.RWMutex
)

// 五分钟检测窗口过期
func cleanupExpiredTokens() {
	for {
		time.Sleep(5 * time.Minute)
		tokenMutex.Lock()
		now := time.Now()
		for token, expiry := range exportTokenExpiration {
			if now.After(expiry) {
				delete(exportTokenCache, token)
				delete(exportTokenExpiration, token)
			}
		}
		tokenMutex.Unlock()
	}
}

func init() {
	go cleanupExpiredTokens()
}

type ExportTemplateApi struct{}

// CreateSysExportTemplateRequest 创建导出模板请求
type CreateSysExportTemplateRequest struct {
	DBName       string                 `json:"dbName"`
	Name         string                 `json:"name" binding:"required"`
	TableName    string                 `json:"tableName"`
	TemplateID   string                 `json:"templateID"`
	TemplateInfo string                 `json:"templateInfo"`
	Limit        *int                   `json:"limit"`
	Order        string                 `json:"order"`
	Conditions   []*ConditionRequest    `json:"conditions"`
	JoinTemplate []*JoinTemplateRequest `json:"joinTemplate"`
}

type ConditionRequest struct {
	TemplateID string `json:"templateID"`
	From       string `json:"from"`
	Column     string `json:"column"`
	Operator   string `json:"operator"`
}

type JoinTemplateRequest struct {
	TemplateID string `json:"templateID"`
	Joins      string `json:"joins"`
	Table      string `json:"table"`
	On         string `json:"on"`
}

// UpdateSysExportTemplateRequest 更新导出模板请求
type UpdateSysExportTemplateRequest struct {
	ID           uint                   `json:"ID" binding:"required"`
	DBName       string                 `json:"dbName"`
	Name         string                 `json:"name" binding:"required"`
	TableName    string                 `json:"tableName"`
	TemplateID   string                 `json:"templateID"`
	TemplateInfo string                 `json:"templateInfo"`
	Limit        *int                   `json:"limit"`
	Order        string                 `json:"order"`
	Conditions   []*ConditionRequest    `json:"conditions"`
	JoinTemplate []*JoinTemplateRequest `json:"joinTemplate"`
}

// DeleteSysExportTemplateRequest 删除导出模板请求
type DeleteSysExportTemplateRequest struct {
	ID uint `json:"ID" binding:"required"`
}

// DeleteSysExportTemplateByIdsRequest 批量删除导出模板请求
type DeleteSysExportTemplateByIdsRequest struct {
	Ids []uint `json:"ids" binding:"required"`
}

// GetSysExportTemplateListRequest 获取导出模板列表请求
type GetSysExportTemplateListRequest struct {
	Page           int        `form:"page"`
	PageSize       int        `form:"pageSize"`
	Name           string     `form:"name"`
	TableName      string     `form:"tableName"`
	TemplateID     string     `form:"templateID"`
	StartCreatedAt *time.Time `form:"startCreatedAt"`
	EndCreatedAt   *time.Time `form:"endCreatedAt"`
}

// CreateSysExportTemplate
// @Tags      SysExportTemplate
// @Summary   创建导出模板
// @Security  ApiKeyAuth
// @accept    application/json
// @Produce   application/json
// @Param     data  body      CreateSysExportTemplateRequest  true  "创建导出模板"
// @Success   200   {object}  response.Response{msg=string}   "创建成功"
// @Router    /sysExportTemplate/createSysExportTemplate [post]
func (e *ExportTemplateApi) CreateSysExportTemplate(c *gin.Context) {
	var req CreateSysExportTemplateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	template := &system.ExportTemplate{
		DBName:       req.DBName,
		Name:         req.Name,
		TableName:    req.TableName,
		TemplateID:   req.TemplateID,
		TemplateInfo: req.TemplateInfo,
		Limit:        req.Limit,
		Order:        req.Order,
	}

	// 转换条件
	if len(req.Conditions) > 0 {
		template.Conditions = make([]*system.Condition, len(req.Conditions))
		for i, c := range req.Conditions {
			template.Conditions[i] = &system.Condition{
				TemplateID: c.TemplateID,
				From:       c.From,
				Column:     c.Column,
				Operator:   c.Operator,
			}
		}
	}

	// 转换关联
	if len(req.JoinTemplate) > 0 {
		template.JoinTemplate = make([]*system.JoinTemplate, len(req.JoinTemplate))
		for i, j := range req.JoinTemplate {
			template.JoinTemplate[i] = &system.JoinTemplate{
				TemplateID: j.TemplateID,
				Joins:      j.Joins,
				Table:      j.Table,
				On:         j.On,
			}
		}
	}

	if err := exportTemplateUsecase.CreateExportTemplate(c, template); err != nil {
		response.FailWithMessage("创建失败", c)
		return
	}
	response.OkWithMessage("创建成功", c)
}

// DeleteSysExportTemplate
// @Tags      SysExportTemplate
// @Summary   删除导出模板
// @Security  ApiKeyAuth
// @accept    application/json
// @Produce   application/json
// @Param     data  body      DeleteSysExportTemplateRequest  true  "删除导出模板"
// @Success   200   {object}  response.Response{msg=string}   "删除成功"
// @Router    /sysExportTemplate/deleteSysExportTemplate [delete]
func (e *ExportTemplateApi) DeleteSysExportTemplate(c *gin.Context) {
	var req DeleteSysExportTemplateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	if err := exportTemplateUsecase.DeleteExportTemplate(c, req.ID); err != nil {
		response.FailWithMessage("删除失败", c)
		return
	}
	response.OkWithMessage("删除成功", c)
}

// DeleteSysExportTemplateByIds
// @Tags      SysExportTemplate
// @Summary   批量删除导出模板
// @Security  ApiKeyAuth
// @accept    application/json
// @Produce   application/json
// @Param     data  body      DeleteSysExportTemplateByIdsRequest  true  "批量删除导出模板"
// @Success   200   {object}  response.Response{msg=string}        "批量删除成功"
// @Router    /sysExportTemplate/deleteSysExportTemplateByIds [delete]
func (e *ExportTemplateApi) DeleteSysExportTemplateByIds(c *gin.Context) {
	var req DeleteSysExportTemplateByIdsRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	if err := exportTemplateUsecase.DeleteExportTemplateByIds(c, req.Ids); err != nil {
		response.FailWithMessage("批量删除失败", c)
		return
	}
	response.OkWithMessage("批量删除成功", c)
}

// UpdateSysExportTemplate
// @Tags      SysExportTemplate
// @Summary   更新导出模板
// @Security  ApiKeyAuth
// @accept    application/json
// @Produce   application/json
// @Param     data  body      UpdateSysExportTemplateRequest  true  "更新导出模板"
// @Success   200   {object}  response.Response{msg=string}   "更新成功"
// @Router    /sysExportTemplate/updateSysExportTemplate [put]
func (e *ExportTemplateApi) UpdateSysExportTemplate(c *gin.Context) {
	var req UpdateSysExportTemplateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	template := &system.ExportTemplate{
		ID:           req.ID,
		DBName:       req.DBName,
		Name:         req.Name,
		TableName:    req.TableName,
		TemplateID:   req.TemplateID,
		TemplateInfo: req.TemplateInfo,
		Limit:        req.Limit,
		Order:        req.Order,
	}

	// 转换条件
	if len(req.Conditions) > 0 {
		template.Conditions = make([]*system.Condition, len(req.Conditions))
		for i, c := range req.Conditions {
			template.Conditions[i] = &system.Condition{
				TemplateID: c.TemplateID,
				From:       c.From,
				Column:     c.Column,
				Operator:   c.Operator,
			}
		}
	}

	// 转换关联
	if len(req.JoinTemplate) > 0 {
		template.JoinTemplate = make([]*system.JoinTemplate, len(req.JoinTemplate))
		for i, j := range req.JoinTemplate {
			template.JoinTemplate[i] = &system.JoinTemplate{
				TemplateID: j.TemplateID,
				Joins:      j.Joins,
				Table:      j.Table,
				On:         j.On,
			}
		}
	}

	if err := exportTemplateUsecase.UpdateExportTemplate(c, template); err != nil {
		response.FailWithMessage("更新失败", c)
		return
	}
	response.OkWithMessage("更新成功", c)
}

// FindSysExportTemplate
// @Tags      SysExportTemplate
// @Summary   用id查询导出模板
// @Security  ApiKeyAuth
// @accept    application/json
// @Produce   application/json
// @Param     ID    query     uint                                                       true  "用id查询导出模板"
// @Success   200   {object}  response.Response{data=map[string]interface{},msg=string}  "查询成功"
// @Router    /sysExportTemplate/findSysExportTemplate [get]
func (e *ExportTemplateApi) FindSysExportTemplate(c *gin.Context) {
	var req struct {
		ID uint `form:"ID" binding:"required"`
	}
	if err := c.ShouldBindQuery(&req); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	template, err := exportTemplateUsecase.GetExportTemplate(c, req.ID)
	if err != nil {
		response.FailWithMessage("查询失败", c)
		return
	}
	response.OkWithData(gin.H{"resysExportTemplate": toExportTemplateResponse(template)}, c)
}

// GetSysExportTemplateList
// @Tags      SysExportTemplate
// @Summary   分页获取导出模板列表
// @Security  ApiKeyAuth
// @accept    application/json
// @Produce   application/json
// @Param     data  query     GetSysExportTemplateListRequest                         true  "分页获取导出模板列表"
// @Success   200   {object}  response.Response{data=response.PageResult,msg=string}  "获取成功"
// @Router    /sysExportTemplate/getSysExportTemplateList [get]
func (e *ExportTemplateApi) GetSysExportTemplateList(c *gin.Context) {
	var req GetSysExportTemplateListRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	searchReq := &system.ExportTemplateSearchReq{
		Page:           req.Page,
		PageSize:       req.PageSize,
		Name:           req.Name,
		TableName:      req.TableName,
		TemplateID:     req.TemplateID,
		StartCreatedAt: req.StartCreatedAt,
		EndCreatedAt:   req.EndCreatedAt,
	}

	list, total, err := exportTemplateUsecase.GetExportTemplateList(c, searchReq)
	if err != nil {
		response.FailWithMessage("获取失败", c)
		return
	}

	respList := make([]interface{}, len(list))
	for i, t := range list {
		respList[i] = toExportTemplateResponse(t)
	}

	response.OkWithDetailed(response.PageResult{
		List:     respList,
		Total:    total,
		Page:     req.Page,
		PageSize: req.PageSize,
	}, "获取成功", c)
}

// ExportExcel
// @Tags      SysExportTemplate
// @Summary   导出表格token
// @Security  ApiKeyAuth
// @accept    application/json
// @Produce   application/json
// @Param     templateID  query     string                                                 true  "模板ID"
// @Success   200         {object}  response.Response{data=string,msg=string}              "获取导出链接"
// @Router    /sysExportTemplate/exportExcel [get]
func (e *ExportTemplateApi) ExportExcel(c *gin.Context) {
	templateID := c.Query("templateID")
	if templateID == "" {
		response.FailWithMessage("模板ID不能为空", c)
		return
	}

	queryParams := c.Request.URL.Query()

	// 创造一次性token
	token := utils.RandomString(32)

	// 记录本次请求参数
	exportParams := map[string]interface{}{
		"templateID":  templateID,
		"queryParams": queryParams,
	}

	// 参数保留记录完成鉴权
	tokenMutex.Lock()
	exportTokenCache[token] = exportParams
	exportTokenExpiration[token] = time.Now().Add(30 * time.Minute)
	tokenMutex.Unlock()

	// 生成一次性链接
	exportUrl := fmt.Sprintf("/sysExportTemplate/exportExcelByToken?token=%s", token)
	response.OkWithData(exportUrl, c)
}

// ExportExcelByToken
// @Tags      ExportExcelByToken
// @Summary   导出表格
// @Security  ApiKeyAuth
// @accept    application/json
// @Produce   application/json
// @Param     token  query  string  true  "导出token"
// @Success   200    {file} csv     "导出CSV文件"
// @Router    /sysExportTemplate/exportExcelByToken [get]
func (e *ExportTemplateApi) ExportExcelByToken(c *gin.Context) {
	token := c.Query("token")
	if token == "" {
		response.FailWithMessage("导出token不能为空", c)
		return
	}

	// 获取token并且从缓存中剔除
	tokenMutex.RLock()
	exportParamsRaw, exists := exportTokenCache[token]
	expiry, _ := exportTokenExpiration[token]
	tokenMutex.RUnlock()

	if !exists || time.Now().After(expiry) {
		response.FailWithMessage("导出token无效或已过期", c)
		return
	}

	// 从token获取参数
	exportParams, ok := exportParamsRaw.(map[string]interface{})
	if !ok {
		response.FailWithMessage("解析导出参数失败", c)
		return
	}

	// 获取导出参数
	templateID := exportParams["templateID"].(string)
	queryParams := exportParams["queryParams"].(url.Values)

	// 清理一次性token
	tokenMutex.Lock()
	delete(exportTokenCache, token)
	delete(exportTokenExpiration, token)
	tokenMutex.Unlock()

	// 导出
	file, name, err := exportTemplateUsecase.ExportExcel(c, templateID, queryParams)
	if err != nil {
		response.FailWithMessage("获取失败", c)
		return
	}

	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", name+utils.RandomString(6)+".csv"))
	c.Header("success", "true")
	c.Data(http.StatusOK, "text/csv", file.Bytes())
}

// PreviewSQL
// @Tags      SysExportTemplate
// @Summary   预览最终生成的SQL
// @Security  ApiKeyAuth
// @accept    application/json
// @Produce   application/json
// @Param     templateID  query     string                                                 true   "导出模板ID"
// @Param     params      query     string                                                 false  "查询参数编码字符串"
// @Success   200         {object}  response.Response{data=map[string]string,msg=string}   "获取成功"
// @Router    /sysExportTemplate/previewSQL [get]
func (e *ExportTemplateApi) PreviewSQL(c *gin.Context) {
	templateID := c.Query("templateID")
	if templateID == "" {
		response.FailWithMessage("模板ID不能为空", c)
		return
	}

	queryParams := c.Request.URL.Query()

	sqlPreview, err := exportTemplateUsecase.PreviewSQL(c, templateID, queryParams)
	if err != nil {
		response.FailWithMessage("获取失败", c)
		return
	}
	response.OkWithData(gin.H{"sql": sqlPreview}, c)
}

// ExportTemplate
// @Tags      SysExportTemplate
// @Summary   导出表格模板
// @Security  ApiKeyAuth
// @accept    application/json
// @Produce   application/json
// @Param     templateID  query     string                                     true  "模板ID"
// @Success   200         {object}  response.Response{data=string,msg=string}  "获取导出链接"
// @Router    /sysExportTemplate/exportTemplate [get]
func (e *ExportTemplateApi) ExportTemplate(c *gin.Context) {
	templateID := c.Query("templateID")
	if templateID == "" {
		response.FailWithMessage("模板ID不能为空", c)
		return
	}

	// 创造一次性token
	token := utils.RandomString(32)

	// 记录本次请求参数
	exportParams := map[string]interface{}{
		"templateID": templateID,
		"isTemplate": true,
	}

	// 参数保留记录完成鉴权
	tokenMutex.Lock()
	exportTokenCache[token] = exportParams
	exportTokenExpiration[token] = time.Now().Add(30 * time.Minute)
	tokenMutex.Unlock()

	// 生成一次性链接
	exportUrl := fmt.Sprintf("/sysExportTemplate/exportTemplateByToken?token=%s", token)
	response.OkWithData(exportUrl, c)
}

// ExportTemplateByToken
// @Tags      ExportTemplateByToken
// @Summary   通过token导出表格模板
// @Security  ApiKeyAuth
// @accept    application/json
// @Produce   application/json
// @Param     token  query  string  true  "导出token"
// @Success   200    {file} csv     "导出CSV模板文件"
// @Router    /sysExportTemplate/exportTemplateByToken [get]
func (e *ExportTemplateApi) ExportTemplateByToken(c *gin.Context) {
	token := c.Query("token")
	if token == "" {
		response.FailWithMessage("导出token不能为空", c)
		return
	}

	// 获取token并且从缓存中剔除
	tokenMutex.RLock()
	exportParamsRaw, exists := exportTokenCache[token]
	expiry, _ := exportTokenExpiration[token]
	tokenMutex.RUnlock()

	if !exists || time.Now().After(expiry) {
		response.FailWithMessage("导出token无效或已过期", c)
		return
	}

	// 从token获取参数
	exportParams, ok := exportParamsRaw.(map[string]interface{})
	if !ok {
		response.FailWithMessage("解析导出参数失败", c)
		return
	}

	// 检查是否为模板导出
	isTemplate, _ := exportParams["isTemplate"].(bool)
	if !isTemplate {
		response.FailWithMessage("token类型错误", c)
		return
	}

	// 获取导出参数
	templateID := exportParams["templateID"].(string)

	// 清理一次性token
	tokenMutex.Lock()
	delete(exportTokenCache, token)
	delete(exportTokenExpiration, token)
	tokenMutex.Unlock()

	// 导出模板
	file, name, err := exportTemplateUsecase.ExportTemplate(c, templateID)
	if err != nil {
		response.FailWithMessage("获取失败", c)
		return
	}

	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", name+"模板.csv"))
	c.Header("success", "true")
	c.Data(http.StatusOK, "text/csv", file.Bytes())
}

// ImportExcel
// @Tags      SysImportTemplate
// @Summary   导入表格
// @Security  ApiKeyAuth
// @accept    multipart/form-data
// @Produce   application/json
// @Param     templateID  query     string                         true  "模板ID"
// @Param     file        formData  file                           true  "导入文件"
// @Success   200         {object}  response.Response{msg=string}  "导入成功"
// @Router    /sysExportTemplate/importExcel [post]
func (e *ExportTemplateApi) ImportExcel(c *gin.Context) {
	templateID := c.Query("templateID")
	if templateID == "" {
		response.FailWithMessage("模板ID不能为空", c)
		return
	}

	file, err := c.FormFile("file")
	if err != nil {
		response.FailWithMessage("文件获取失败", c)
		return
	}

	if err := exportTemplateUsecase.ImportExcel(c, templateID, file); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithMessage("导入成功", c)
}

// 转换为响应结构
func toExportTemplateResponse(t *system.ExportTemplate) map[string]interface{} {
	resp := map[string]interface{}{
		"ID":           t.ID,
		"dbName":       t.DBName,
		"name":         t.Name,
		"tableName":    t.TableName,
		"templateID":   t.TemplateID,
		"templateInfo": t.TemplateInfo,
		"limit":        t.Limit,
		"order":        t.Order,
		"createdAt":    t.CreatedAt,
		"updatedAt":    t.UpdatedAt,
	}

	if len(t.Conditions) > 0 {
		conditions := make([]map[string]interface{}, len(t.Conditions))
		for i, c := range t.Conditions {
			conditions[i] = map[string]interface{}{
				"ID":         c.ID,
				"templateID": c.TemplateID,
				"from":       c.From,
				"column":     c.Column,
				"operator":   c.Operator,
			}
		}
		resp["conditions"] = conditions
	}

	if len(t.JoinTemplate) > 0 {
		joins := make([]map[string]interface{}, len(t.JoinTemplate))
		for i, j := range t.JoinTemplate {
			joins[i] = map[string]interface{}{
				"ID":         j.ID,
				"templateID": j.TemplateID,
				"joins":      j.Joins,
				"table":      j.Table,
				"on":         j.On,
			}
		}
		resp["joinTemplate"] = joins
	}

	return resp
}
