package repositories

import (
	// "log"
	"fmt"
	"net/url"
	"strings"
	"time"

	"github.com/niangaodev/art-code/config"
	"github.com/niangaodev/art-code/models"
)

// Helper to parse date string to unix timestamp
func parseDateToUnix(dateStr string, isEnd bool) int64 {
	if dateStr == "" {
		return 0
	}

	// 处理URL编码格式：先尝试URL解码，然后将+替换为空格
	decoded := dateStr
	if decodedStr, err := url.QueryUnescape(dateStr); err == nil {
		decoded = decodedStr
	}
	// URL编码中+可能代表空格，需要替换
	decoded = strings.ReplaceAll(decoded, "+", " ")

	// Try parsing with time first
	t, err := time.ParseInLocation("2006-01-02 15:04", decoded, time.Local)
	if err == nil {
		if isEnd {
			// HH:mm:59
			return t.Add(59 * time.Second).Unix()
		}
		return t.Unix()
	}

	// Try parsing just date
	t, err = time.ParseInLocation("2006-01-02", decoded, time.Local)
	if err == nil {
		if isEnd {
			// 23:59:59
			return t.Add(24*time.Hour - 1*time.Second).Unix()
		}
		return t.Unix()
	}

	return 0
}

// CreateAccessLog 创建访问日志
func CreateAccessLog(log *models.AccessLog) error {
	return config.DB.Create(log).Error
}

// UVTrendData UV趋势数据
type UVTrendData struct {
	Date  string  `json:"date"`
	Count int     `json:"value"`
	YoY   float64 `json:"yoy"`
	MoM   float64 `json:"mom"`
}

// GetDailyUV 获取UV趋势
func GetDailyUV(startDate, endDate string) ([]UVTrendData, error) {
	// 确定日期范围
	var startTime, endTime time.Time
	if startDate != "" {
		startUnix := parseDateToUnix(startDate, false)
		startTime = time.Unix(startUnix, 0)
	} else {
		startTime = time.Now().AddDate(0, 0, -6)
		startTime = time.Date(startTime.Year(), startTime.Month(), startTime.Day(), 0, 0, 0, 0, time.Local)
	}

	if endDate != "" {
		endUnix := parseDateToUnix(endDate, true)
		endTime = time.Unix(endUnix, 0)
	} else {
		endTime = time.Now()
		endTime = time.Date(endTime.Year(), endTime.Month(), endTime.Day(), 23, 59, 59, 0, time.Local)
	}

	// 查询数据库
	query := config.DB.Model(&models.UserAccessLog{}).
		Select("FROM_UNIXTIME(access_time, '%Y-%m-%d') as date, COUNT(DISTINCT user_ip) as count").
		Where("access_time >= ?", startTime.Unix()).
		Where("access_time <= ?", endTime.Unix())

	var results []UVTrendData
	err := query.Group("date").
		Order("date ASC").
		Scan(&results).Error

	if err != nil {
		return nil, err
	}

	// 创建日期到数据的映射
	resultMap := make(map[string]UVTrendData)
	for _, r := range results {
		resultMap[r.Date] = r
	}

	// 生成完整日期列表
	var fullResults []UVTrendData
	current := time.Date(startTime.Year(), startTime.Month(), startTime.Day(), 0, 0, 0, 0, time.Local)
	endDay := time.Date(endTime.Year(), endTime.Month(), endTime.Day(), 0, 0, 0, 0, time.Local)

	for !current.After(endDay) {
		dateStr := current.Format("2006-01-02")
		if data, exists := resultMap[dateStr]; exists {
			data.YoY = 0
			data.MoM = 0
			fullResults = append(fullResults, data)
		} else {
			// 填充0值
			fullResults = append(fullResults, UVTrendData{
				Date:  dateStr,
				Count: 0,
				YoY:   0,
				MoM:   0,
			})
		}
		current = current.AddDate(0, 0, 1)
	}

	return fullResults, nil
}

// GetAccessLogs 获取访问日志列表（支持分页和筛选）
func GetAccessLogs(page, pageSize int, postID *int, filter AccessLogFilter) ([]models.AccessLog, int64, error) {
	query := config.DB.Model(&models.AccessLog{}).
		Where("deleted_at = ?", 0)

	// 如果指定了文章ID，筛选该文章的访问记录
	if postID != nil {
		// 路径格式可能是：
		// - /api/posts/{id} (API调用)
		// - /blog/{id} (前端页面访问)
		// - /posts/{id} (其他可能的格式)
		// 使用精确的匹配，避免匹配到其他ID（如123匹配到1234）
		// 使用LIKE模式，确保ID后面是 / 或 ? 或 字符串结束
		postIDStr := fmt.Sprintf("%d", *postID)
		// 匹配精确的路径格式，避免部分匹配
		// 例如：/api/posts/123 或 /api/posts/123/ 或 /api/posts/123?xxx
		// 但不匹配 /api/posts/1234
		// 使用精确的 LIKE 匹配，确保只匹配正确的文章ID
		// 匹配格式：/api/posts/{id}、/api/posts/{id}/、/api/posts/{id}?xxx
		// 匹配格式：/blog/{id}、/blog/{id}/、/blog/{id}?xxx
		// 匹配格式：/posts/{id}、/posts/{id}/、/posts/{id}?xxx
		query = query.Where(
			"(path = ? OR path LIKE ? OR path LIKE ? OR "+
				"path = ? OR path LIKE ? OR path LIKE ? OR "+
				"path = ? OR path LIKE ? OR path LIKE ?)",
			// /api/posts/{id} 格式（3个参数）
			fmt.Sprintf("/api/posts/%s", postIDStr),
			fmt.Sprintf("/api/posts/%s/%%", postIDStr),
			fmt.Sprintf("/api/posts/%s?%%", postIDStr),
			// /blog/{id} 格式（3个参数）
			fmt.Sprintf("/blog/%s", postIDStr),
			fmt.Sprintf("/blog/%s/%%", postIDStr),
			fmt.Sprintf("/blog/%s?%%", postIDStr),
			// /posts/{id} 格式（3个参数）
			fmt.Sprintf("/posts/%s", postIDStr),
			fmt.Sprintf("/posts/%s/%%", postIDStr),
			fmt.Sprintf("/posts/%s?%%", postIDStr),
		)
	}

	if filter.Path != "" {
		query = query.Where("path LIKE ?", "%"+filter.Path+"%")
	}
	if filter.Region != "" {
		query = query.Where("region LIKE ?", "%"+filter.Region+"%")
	}
	if filter.StartDate != "" {
		startUnix := parseDateToUnix(filter.StartDate, false)
		if startUnix > 0 {
			query = query.Where("created_at >= ?", startUnix)
		}
	}
	if filter.EndDate != "" {
		endUnix := parseDateToUnix(filter.EndDate, true)
		if endUnix > 0 {
			query = query.Where("created_at <= ?", endUnix)
		}
	}

	var total int64
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	var logs []models.AccessLog
	offset := (page - 1) * pageSize
	err := query.Order("created_at DESC").
		Limit(pageSize).
		Offset(offset).
		Find(&logs).Error

	return logs, total, err
}

// GetPostAccessLogsFromAccessLogs 从 access_logs 表获取指定文章的访问记录（已废弃，应使用 user_access_logs）
// 保留此函数以保持向后兼容，但建议使用 user_access_log_repository.GetPostAccessLogs
func GetPostAccessLogsFromAccessLogs(postID int, page, pageSize int) ([]models.AccessLog, int64, error) {
	return GetAccessLogs(page, pageSize, &postID, AccessLogFilter{})
}

// ExtractProvinceFromRegion 从归属地字符串中提取省份信息
// 格式: 国家|区域|省份|城市|ISP
// 例如: 中国|0|浙江|杭州市|联通 -> 浙江
func ExtractProvinceFromRegion(region string) string {
	if region == "" || region == "Unknown" || region == "Internal" {
		return "未知"
	}

	parts := strings.Split(region, "|")
	if len(parts) >= 3 {
		province := strings.TrimSpace(parts[2])
		if province != "" && province != "0" {
			// 移除"省"、"市"、"自治区"等后缀，统一格式
			province = strings.TrimSuffix(province, "省")
			province = strings.TrimSuffix(province, "市")
			province = strings.TrimSuffix(province, "自治区")
			province = strings.TrimSuffix(province, "特别行政区")
			return province
		}
	}

	return "未知"
}

// 所有省份列表（34个）
var allProvinces = []string{
	"北京", "天津", "河北", "山西", "内蒙古", "辽宁", "吉林", "黑龙江",
	"上海", "江苏", "浙江", "安徽", "福建", "江西", "山东", "河南",
	"湖北", "湖南", "广东", "广西", "海南", "重庆", "四川", "贵州",
	"云南", "西藏", "陕西", "甘肃", "青海", "宁夏", "新疆", "台湾", "香港", "澳门",
}

// GetUserRegionsFromAccessLogs 获取用户地域分布（使用 access_logs 表的 region 字段）
// 返回所有34个省份的数据，没有数据的省份 Count 设为 0
// 注意：此函数查询的是所有访问记录，包括静态资源、API调用等
// 建议使用 GetUserRegionsFromUserAccessLogs 获取更准确的用户访问统计
func GetUserRegionsFromAccessLogs(startDate, endDate string) ([]struct {
	Region string
	Count  int
}, error) {
	query := config.DB.Model(&models.AccessLog{}).
		Select("COALESCE(NULLIF(region, ''), 'Unknown') as region, COUNT(DISTINCT ip) as count").
		Where("deleted_at = ?", 0)

	if startDate != "" {
		startUnix := parseDateToUnix(startDate, false)
		query = query.Where("created_at >= ?", startUnix)
	}

	if endDate != "" {
		endUnix := parseDateToUnix(endDate, true)
		query = query.Where("created_at <= ?", endUnix)
	}

	var results []struct {
		Region string
		Count  int
	}
	err := query.Group("region").
		Order("count DESC").
		Limit(50).
		Scan(&results).Error

	if err != nil {
		return nil, err
	}

	// 解析归属地，提取省份信息并聚合
	provinceMap := make(map[string]int)
	for _, r := range results {
		province := ExtractProvinceFromRegion(r.Region)
		if province != "未知" {
			provinceMap[province] += r.Count
		}
	}

	// 为所有省份生成数据，没有数据的设为0
	var finalResults []struct {
		Region string
		Count  int
	}
	for _, province := range allProvinces {
		count := provinceMap[province]
		finalResults = append(finalResults, struct {
			Region string
			Count  int
		}{
			Region: province,
			Count:  count,
		})
	}

	return finalResults, nil
}

// GetDefaultUserRegions 返回所有34个省份的默认数据（Count为0）
func GetDefaultUserRegions() []struct {
	Region string
	Count  int
} {
	var defaultResults []struct {
		Region string
		Count  int
	}
	for _, province := range allProvinces {
		defaultResults = append(defaultResults, struct {
			Region string
			Count  int
		}{
			Region: province,
			Count:  0,
		})
	}
	return defaultResults
}
