package system

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"mime/multipart"
	"net/url"
	"strconv"
	"strings"
	"time"
)

// ExportTemplate 导出模板实体
type ExportTemplate struct {
	ID           uint
	DBName       string
	Name         string
	TableName    string
	TemplateID   string
	TemplateInfo string
	Limit        *int
	Order        string
	Conditions   []*Condition
	JoinTemplate []*JoinTemplate
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

// Condition 条件实体
type Condition struct {
	ID         uint
	TemplateID string
	From       string
	Column     string
	Operator   string
}

// JoinTemplate 关联模板实体
type JoinTemplate struct {
	ID         uint
	TemplateID string
	Joins      string
	Table      string
	On         string
}

// ExportTemplateSearchReq 导出模板搜索请求
type ExportTemplateSearchReq struct {
	Page           int
	PageSize       int
	Name           string
	TableName      string
	TemplateID     string
	StartCreatedAt *time.Time
	EndCreatedAt   *time.Time
}

// ExportTemplateRepo 导出模板仓储接口
type ExportTemplateRepo interface {
	Create(ctx context.Context, template *ExportTemplate) error
	Update(ctx context.Context, template *ExportTemplate) error
	Delete(ctx context.Context, id uint) error
	FindByID(ctx context.Context, id uint) (*ExportTemplate, error)
	FindByTemplateID(ctx context.Context, templateID string) (*ExportTemplate, error)
	GetList(ctx context.Context, req *ExportTemplateSearchReq) ([]*ExportTemplate, int64, error)
	DeleteConditionsByTemplateID(ctx context.Context, templateID string) error
	DeleteJoinsByTemplateID(ctx context.Context, templateID string) error
	CreateConditions(ctx context.Context, conditions []*Condition) error
	CreateJoins(ctx context.Context, joins []*JoinTemplate) error
	// Excel 相关
	GetDB(dbName string) interface{}
	ExecuteQuery(ctx context.Context, dbName, sql string, args ...interface{}) ([]map[string]interface{}, error)
	GetColumnTypes(ctx context.Context, dbName, tableName string) ([]string, error)
	HasDeletedAtColumn(ctx context.Context, tableName string) bool
	ImportData(ctx context.Context, dbName, tableName string, items []map[string]interface{}) error
}

// ExportTemplateUsecase 导出模板用例
type ExportTemplateUsecase struct {
	repo ExportTemplateRepo
}

// NewExportTemplateUsecase 创建导出模板用例
func NewExportTemplateUsecase(repo ExportTemplateRepo) *ExportTemplateUsecase {
	return &ExportTemplateUsecase{repo: repo}
}

// CreateExportTemplate 创建导出模板
func (uc *ExportTemplateUsecase) CreateExportTemplate(ctx context.Context, template *ExportTemplate) error {
	return uc.repo.Create(ctx, template)
}

// DeleteExportTemplate 删除导出模板
func (uc *ExportTemplateUsecase) DeleteExportTemplate(ctx context.Context, id uint) error {
	return uc.repo.Delete(ctx, id)
}

// DeleteExportTemplateByIds 批量删除导出模板
func (uc *ExportTemplateUsecase) DeleteExportTemplateByIds(ctx context.Context, ids []uint) error {
	for _, id := range ids {
		if err := uc.repo.Delete(ctx, id); err != nil {
			return err
		}
	}
	return nil
}

// UpdateExportTemplate 更新导出模板
func (uc *ExportTemplateUsecase) UpdateExportTemplate(ctx context.Context, template *ExportTemplate) error {
	// 删除旧的条件和关联
	if err := uc.repo.DeleteConditionsByTemplateID(ctx, template.TemplateID); err != nil {
		return err
	}
	if err := uc.repo.DeleteJoinsByTemplateID(ctx, template.TemplateID); err != nil {
		return err
	}

	// 保存条件
	conditions := template.Conditions
	template.Conditions = nil

	// 保存关联
	joins := template.JoinTemplate
	template.JoinTemplate = nil

	// 更新模板
	if err := uc.repo.Update(ctx, template); err != nil {
		return err
	}

	// 创建新的条件
	if len(conditions) > 0 {
		for i := range conditions {
			conditions[i].ID = 0
		}
		if err := uc.repo.CreateConditions(ctx, conditions); err != nil {
			return err
		}
	}

	// 创建新的关联
	if len(joins) > 0 {
		for i := range joins {
			joins[i].ID = 0
		}
		if err := uc.repo.CreateJoins(ctx, joins); err != nil {
			return err
		}
	}

	return nil
}

// GetExportTemplate 根据ID获取导出模板
func (uc *ExportTemplateUsecase) GetExportTemplate(ctx context.Context, id uint) (*ExportTemplate, error) {
	return uc.repo.FindByID(ctx, id)
}

// GetExportTemplateList 分页获取导出模板列表
func (uc *ExportTemplateUsecase) GetExportTemplateList(ctx context.Context, req *ExportTemplateSearchReq) ([]*ExportTemplate, int64, error) {
	return uc.repo.GetList(ctx, req)
}

// ExportExcel 导出Excel
func (uc *ExportTemplateUsecase) ExportExcel(ctx context.Context, templateID string, values url.Values) (*bytes.Buffer, string, error) {
	params := values.Get("params")
	paramsValues, err := url.ParseQuery(params)
	if err != nil {
		return nil, "", fmt.Errorf("解析 params 参数失败: %v", err)
	}

	template, err := uc.repo.FindByTemplateID(ctx, templateID)
	if err != nil {
		return nil, "", err
	}

	// 解析模板信息
	var templateInfoMap = make(map[string]string)
	columns, err := getJSONKeys(template.TemplateInfo)
	if err != nil {
		return nil, "", err
	}
	if err := json.Unmarshal([]byte(template.TemplateInfo), &templateInfoMap); err != nil {
		return nil, "", err
	}

	var tableTitle []string
	var selectKeyFmt []string
	for _, key := range columns {
		selectKeyFmt = append(selectKeyFmt, key)
		tableTitle = append(tableTitle, templateInfoMap[key])
	}

	selects := strings.Join(selectKeyFmt, ", ")

	// 构建SQL
	var sb strings.Builder
	sb.WriteString("SELECT ")
	sb.WriteString(selects)
	sb.WriteString(" FROM ")
	sb.WriteString(template.TableName)

	// JOIN
	if len(template.JoinTemplate) > 0 {
		for _, join := range template.JoinTemplate {
			sb.WriteString(" ")
			sb.WriteString(join.Joins)
			sb.WriteString(" ")
			sb.WriteString(join.Table)
			sb.WriteString(" ON ")
			sb.WriteString(join.On)
		}
	}

	// WHERE
	var wheres []string
	var args []interface{}

	// 软删除过滤
	filterDeleted := paramsValues.Get("filterDeleted") == "true"
	if filterDeleted {
		wheres = append(wheres, fmt.Sprintf("%s.deleted_at IS NULL", template.TableName))
		for _, join := range template.JoinTemplate {
			if uc.repo.HasDeletedAtColumn(ctx, join.Table) {
				wheres = append(wheres, fmt.Sprintf("%s.deleted_at IS NULL", join.Table))
			}
		}
	}

	// 条件
	for _, condition := range template.Conditions {
		value := paramsValues.Get(condition.From)
		op := strings.ToUpper(strings.TrimSpace(condition.Operator))

		if op == "BETWEEN" {
			startValue := paramsValues.Get("start" + condition.From)
			endValue := paramsValues.Get("end" + condition.From)
			if startValue != "" && endValue != "" {
				wheres = append(wheres, fmt.Sprintf("%s BETWEEN ? AND ?", condition.Column))
				args = append(args, startValue, endValue)
			}
			continue
		}

		if value == "" {
			continue
		}

		if op == "LIKE" {
			wheres = append(wheres, fmt.Sprintf("%s LIKE ?", condition.Column))
			args = append(args, "%"+value+"%")
		} else if op == "IN" || op == "NOT IN" {
			wheres = append(wheres, fmt.Sprintf("%s %s (?)", condition.Column, op))
			args = append(args, value)
		} else {
			wheres = append(wheres, fmt.Sprintf("%s %s ?", condition.Column, op))
			args = append(args, value)
		}
	}

	if len(wheres) > 0 {
		sb.WriteString(" WHERE ")
		sb.WriteString(strings.Join(wheres, " AND "))
	}

	// ORDER
	order := paramsValues.Get("order")
	if order == "" && template.Order != "" {
		order = template.Order
	}
	if order != "" {
		sb.WriteString(" ORDER BY ")
		sb.WriteString(order)
	}

	// LIMIT
	limit := paramsValues.Get("limit")
	if limit == "" && template.Limit != nil && *template.Limit != 0 {
		limit = strconv.Itoa(*template.Limit)
	}
	if limit != "" {
		sb.WriteString(" LIMIT ")
		sb.WriteString(limit)
	}

	// OFFSET
	offset := paramsValues.Get("offset")
	if offset != "" {
		sb.WriteString(" OFFSET ")
		sb.WriteString(offset)
	}

	// 执行查询
	tableMap, err := uc.repo.ExecuteQuery(ctx, template.DBName, sb.String(), args...)
	if err != nil {
		return nil, "", err
	}

	// 生成Excel
	return uc.generateExcel(tableMap, columns, tableTitle, template)
}

// generateExcel 生成Excel文件
func (uc *ExportTemplateUsecase) generateExcel(tableMap []map[string]interface{}, columns, tableTitle []string, template *ExportTemplate) (*bytes.Buffer, string, error) {
	// 简化实现：生成CSV格式
	var buf bytes.Buffer

	// 写入标题行
	buf.WriteString(strings.Join(tableTitle, ","))
	buf.WriteString("\n")

	// 写入数据行
	for _, row := range tableMap {
		var values []string
		for _, col := range columns {
			col = strings.ReplaceAll(col, "\"", "")
			col = strings.ReplaceAll(col, "`", "")
			if len(template.JoinTemplate) > 0 {
				columnAs := strings.Split(col, " as ")
				if len(columnAs) > 1 {
					col = strings.TrimSpace(columnAs[1])
				} else {
					columnArr := strings.Split(col, ".")
					if len(columnArr) > 1 {
						col = columnArr[1]
					}
				}
			}
			if t, ok := row[col].(time.Time); ok {
				values = append(values, t.Format("2006-01-02 15:04:05"))
			} else {
				values = append(values, fmt.Sprintf("%v", row[col]))
			}
		}
		buf.WriteString(strings.Join(values, ","))
		buf.WriteString("\n")
	}

	return &buf, template.Name, nil
}

// PreviewSQL 预览SQL
func (uc *ExportTemplateUsecase) PreviewSQL(ctx context.Context, templateID string, values url.Values) (string, error) {
	params := values.Get("params")
	paramsValues, _ := url.ParseQuery(params)

	template, err := uc.repo.FindByTemplateID(ctx, templateID)
	if err != nil {
		return "", err
	}

	// 解析模板信息
	var templateInfoMap = make(map[string]string)
	columns, err := getJSONKeys(template.TemplateInfo)
	if err != nil {
		return "", err
	}
	if err := json.Unmarshal([]byte(template.TemplateInfo), &templateInfoMap); err != nil {
		return "", err
	}

	var selectKeyFmt []string
	for _, key := range columns {
		selectKeyFmt = append(selectKeyFmt, key)
	}
	selects := strings.Join(selectKeyFmt, ", ")

	// 构建SQL
	var sb strings.Builder
	sb.WriteString("SELECT ")
	sb.WriteString(selects)
	sb.WriteString(" FROM ")
	sb.WriteString(template.TableName)

	// JOIN
	if len(template.JoinTemplate) > 0 {
		for _, join := range template.JoinTemplate {
			sb.WriteString(" ")
			sb.WriteString(join.Joins)
			sb.WriteString(" ")
			sb.WriteString(join.Table)
			sb.WriteString(" ON ")
			sb.WriteString(join.On)
		}
	}

	// WHERE
	var wheres []string

	filterDeleted := false
	if paramsValues != nil {
		filterDeleted = paramsValues.Get("filterDeleted") == "true"
	}
	if filterDeleted {
		wheres = append(wheres, fmt.Sprintf("%s.deleted_at IS NULL", template.TableName))
		for _, join := range template.JoinTemplate {
			if uc.repo.HasDeletedAtColumn(ctx, join.Table) {
				wheres = append(wheres, fmt.Sprintf("%s.deleted_at IS NULL", join.Table))
			}
		}
	}

	// 条件
	for _, condition := range template.Conditions {
		op := strings.ToUpper(strings.TrimSpace(condition.Operator))
		col := strings.TrimSpace(condition.Column)

		val := ""
		if paramsValues != nil {
			val = paramsValues.Get(condition.From)
		}

		switch op {
		case "BETWEEN":
			startValue := ""
			endValue := ""
			if paramsValues != nil {
				startValue = paramsValues.Get("start" + condition.From)
				endValue = paramsValues.Get("end" + condition.From)
			}
			if startValue != "" && endValue != "" {
				wheres = append(wheres, fmt.Sprintf("%s BETWEEN '%s' AND '%s'", col, startValue, endValue))
			} else {
				wheres = append(wheres, fmt.Sprintf("%s BETWEEN {start%s} AND {end%s}", col, condition.From, condition.From))
			}
		case "IN", "NOT IN":
			if val != "" {
				wheres = append(wheres, fmt.Sprintf("%s %s ('%s')", col, op, val))
			} else {
				wheres = append(wheres, fmt.Sprintf("%s %s ({%s})", col, op, condition.From))
			}
		case "LIKE":
			if val != "" {
				wheres = append(wheres, fmt.Sprintf("%s LIKE '%%%s%%'", col, val))
			} else {
				wheres = append(wheres, fmt.Sprintf("%s LIKE {%%%s%%}", col, condition.From))
			}
		default:
			if val != "" {
				wheres = append(wheres, fmt.Sprintf("%s %s '%s'", col, op, val))
			} else {
				wheres = append(wheres, fmt.Sprintf("%s %s {%s}", col, op, condition.From))
			}
		}
	}

	if len(wheres) > 0 {
		sb.WriteString(" WHERE ")
		sb.WriteString(strings.Join(wheres, " AND "))
	}

	// ORDER
	order := ""
	if paramsValues != nil {
		order = paramsValues.Get("order")
	}
	if order == "" && template.Order != "" {
		order = template.Order
	}
	if order != "" {
		sb.WriteString(" ORDER BY ")
		sb.WriteString(order)
	}

	// LIMIT/OFFSET
	limitStr := ""
	offsetStr := ""
	if paramsValues != nil {
		limitStr = paramsValues.Get("limit")
		offsetStr = paramsValues.Get("offset")
	}
	if limitStr == "" && template.Limit != nil && *template.Limit != 0 {
		limitStr = strconv.Itoa(*template.Limit)
	}

	limitInt := 0
	offsetInt := 0
	if limitStr != "" {
		if v, e := strconv.Atoi(limitStr); e == nil {
			limitInt = v
		}
	}
	if offsetStr != "" {
		if v, e := strconv.Atoi(offsetStr); e == nil {
			offsetInt = v
		}
	}

	if limitInt > 0 {
		sb.WriteString(" LIMIT ")
		sb.WriteString(strconv.Itoa(limitInt))
		if offsetInt > 0 {
			sb.WriteString(" OFFSET ")
			sb.WriteString(strconv.Itoa(offsetInt))
		}
	} else if offsetInt > 0 {
		sb.WriteString(" OFFSET ")
		sb.WriteString(strconv.Itoa(offsetInt))
	}

	return sb.String(), nil
}

// ExportTemplate 导出Excel模板
func (uc *ExportTemplateUsecase) ExportTemplate(ctx context.Context, templateID string) (*bytes.Buffer, string, error) {
	template, err := uc.repo.FindByTemplateID(ctx, templateID)
	if err != nil {
		return nil, "", err
	}

	var templateInfoMap = make(map[string]string)
	columns, err := getJSONKeys(template.TemplateInfo)
	if err != nil {
		return nil, "", err
	}
	if err := json.Unmarshal([]byte(template.TemplateInfo), &templateInfoMap); err != nil {
		return nil, "", err
	}

	var tableTitle []string
	for _, key := range columns {
		tableTitle = append(tableTitle, templateInfoMap[key])
	}

	// 生成CSV模板
	var buf bytes.Buffer
	buf.WriteString(strings.Join(tableTitle, ","))
	buf.WriteString("\n")

	return &buf, template.Name, nil
}

// ImportExcel 导入Excel
func (uc *ExportTemplateUsecase) ImportExcel(ctx context.Context, templateID string, file *multipart.FileHeader) error {
	template, err := uc.repo.FindByTemplateID(ctx, templateID)
	if err != nil {
		return err
	}

	src, err := file.Open()
	if err != nil {
		return err
	}
	defer src.Close()

	// 简化实现：读取CSV格式
	var templateInfoMap = make(map[string]string)
	if err := json.Unmarshal([]byte(template.TemplateInfo), &templateInfoMap); err != nil {
		return err
	}

	var titleKeyMap = make(map[string]string)
	for key, title := range templateInfoMap {
		titleKeyMap[title] = key
	}

	// 这里需要实际的Excel解析逻辑
	return errors.New("Excel导入功能需要excelize库支持")
}

// getJSONKeys 获取JSON对象的键（保持顺序）
func getJSONKeys(jsonStr string) ([]string, error) {
	var result []string
	dec := json.NewDecoder(strings.NewReader(jsonStr))

	// 读取开始的 {
	t, err := dec.Token()
	if err != nil {
		return nil, err
	}
	if t != json.Delim('{') {
		return nil, errors.New("expected {")
	}

	for dec.More() {
		// 读取键
		t, err := dec.Token()
		if err != nil {
			return nil, err
		}
		key, ok := t.(string)
		if !ok {
			return nil, errors.New("expected string key")
		}
		result = append(result, key)

		// 跳过值
		var value interface{}
		if err := dec.Decode(&value); err != nil {
			return nil, err
		}
	}

	return result, nil
}
