package services

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"regexp"
	"strings"
	"time"
)

// TrialExpiryChecker checks for trial expiry and sends notifications
type TrialExpiryChecker struct {
	feishuWebhook string
}

// NewTrialExpiryChecker creates a new trial expiry checker
func NewTrialExpiryChecker(feishuWebhook string) *TrialExpiryChecker {
	return &TrialExpiryChecker{
		feishuWebhook: feishuWebhook,
	}
}

// Customer represents a customer record
type Customer struct {
	ID              string `json:"id"`
	CreatedAt       string `json:"createdAt"`
	CustomerName    string `json:"customerName"`
	IntendedProduct string `json:"intendedProduct"`
	Version         string `json:"version"`
	Description     string `json:"description"`
	Solution        string `json:"solution"`
	Type            string `json:"type"`
	Module          string `json:"module"`
	StatusProgress  string `json:"statusProgress"`
	Reporter        string `json:"reporter"` // Now used for trial period
}

// TrialPeriod represents a trial period record
type TrialPeriod struct {
	ID           string    `json:"id"`
	CustomerName string    `json:"customerName"`
	StartTime    time.Time `json:"startTime"`
	EndTime      time.Time `json:"endTime"`
	CreatedAt    time.Time `json:"createdAt"`
}

// ParseTrialPeriod parses the trial period string
// Supports formats like: "2026/1/5～2026/1/16", "2026/1/5~2026/1/16", "2026-1-5～2026-1-16"
func ParseTrialPeriod(trialStr string) (startDate, endDate time.Time, err error) {
	if trialStr == "" {
		return time.Time{}, time.Time{}, fmt.Errorf("empty trial period")
	}

	// Replace different separators with standard ~
	trialStr = strings.ReplaceAll(trialStr, "～", "~")
	trialStr = strings.ReplaceAll(trialStr, " ", "")

	// Split by ~
	parts := strings.Split(trialStr, "~")
	if len(parts) != 2 {
		return time.Time{}, time.Time{}, fmt.Errorf("invalid trial period format")
	}

	// Parse dates - support multiple formats
	layouts := []string{
		"2006/1/2",
		"2006-1-2",
		"2006/01/02",
		"2006-01-02",
	}

	var parseErr error
	for _, layout := range layouts {
		startDate, parseErr = time.Parse(layout, strings.TrimSpace(parts[0]))
		if parseErr == nil {
			break
		}
	}
	if parseErr != nil {
		return time.Time{}, time.Time{}, fmt.Errorf("failed to parse start date: %v", parseErr)
	}

	for _, layout := range layouts {
		endDate, parseErr = time.Parse(layout, strings.TrimSpace(parts[1]))
		if parseErr == nil {
			break
		}
	}
	if parseErr != nil {
		return time.Time{}, time.Time{}, fmt.Errorf("failed to parse end date: %v", parseErr)
	}

	return startDate, endDate, nil
}

// CheckAndNotify checks for customers whose trial expires soon and sends notifications
func (t *TrialExpiryChecker) CheckAndNotify(customers []Customer) error {
	if t.feishuWebhook == "" {
		log.Println("Feishu webhook not configured, skipping trial expiry notifications")
		return nil
	}

	now := time.Now()
	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())

	for _, customer := range customers {
		if customer.Reporter == "" {
			continue
		}

		_, endDate, err := ParseTrialPeriod(customer.Reporter)
		if err != nil {
			// Skip invalid trial periods
			continue
		}

		// Check if trial expires within 3 days
		endDateOnly := time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 0, 0, 0, 0, endDate.Location())
		daysUntilExpiry := int(endDateOnly.Sub(today).Hours() / 24)

		// Send notification for trials expiring today, tomorrow, or within 3 days
		if daysUntilExpiry >= 0 && daysUntilExpiry <= 3 {
			err := t.sendExpiryNotification(customer.CustomerName, customer.Reporter, daysUntilExpiry)
			if err != nil {
				log.Printf("Failed to send expiry notification for %s: %v", customer.CustomerName, err)
			} else {
				log.Printf("Sent trial expiry notification for customer: %s (expires in %d days)", customer.CustomerName, daysUntilExpiry)
			}
		}
	}

	return nil
}

// CheckTrialPeriodsAndNotify checks trial periods and sends notifications
func (t *TrialExpiryChecker) CheckTrialPeriodsAndNotify(trialPeriods []TrialPeriod, customersMap map[string]string) error {
	if t.feishuWebhook == "" {
		log.Println("Feishu webhook not configured, skipping trial expiry notifications")
		return nil
	}

	now := time.Now()
	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())

	for _, period := range trialPeriods {
		endDateOnly := time.Date(period.EndTime.Year(), period.EndTime.Month(), period.EndTime.Day(), 0, 0, 0, 0, period.EndTime.Location())
		daysUntilExpiry := int(endDateOnly.Sub(today).Hours() / 24)

		// Send notification for trials expiring today, tomorrow, or within 3 days
		if daysUntilExpiry >= 0 && daysUntilExpiry <= 3 {
			customerName := period.CustomerName
			if customerName == "" {
				customerName = "未知客户"
			}

			trialPeriodStr := fmt.Sprintf("%s～%s",
				period.StartTime.Format("2006/1/2 15:04"),
				period.EndTime.Format("2006/1/2 15:04"))

			err := t.sendExpiryNotification(customerName, trialPeriodStr, daysUntilExpiry)
			if err != nil {
				log.Printf("Failed to send expiry notification for %s: %v", customerName, err)
			} else {
				log.Printf("Sent trial expiry notification for customer: %s (expires in %d days)", customerName, daysUntilExpiry)
			}
		}
	}

	return nil
}

// sendExpiryNotification sends a rich Feishu card notification for trial expiry
func (t *TrialExpiryChecker) sendExpiryNotification(customerName, trialPeriod string, daysUntilExpiry int) error {
	var title, urgencyLevel, urgencyColor, expiryText string

	// Determine urgency level and message based on days until expiry
	switch daysUntilExpiry {
	case 0:
		title = "🔴 试用今日到期提醒"
		urgencyLevel = "紧急"
		urgencyColor = "red"
		expiryText = "今天"
	case 1:
		title = "🟠 试用明日到期提醒"
		urgencyLevel = "重要"
		urgencyColor = "orange"
		expiryText = "明天"
	case 2:
		title = "🟡 试用即将到期提醒"
		urgencyLevel = "提醒"
		urgencyColor = "blue"
		expiryText = "2天后"
	case 3:
		title = "🔵 试用即将到期提醒"
		urgencyLevel = "提醒"
		urgencyColor = "blue"
		expiryText = "3天后"
	default:
		title = "📅 试用到期提醒"
		urgencyLevel = "提醒"
		urgencyColor = "blue"
		expiryText = fmt.Sprintf("%d天后", daysUntilExpiry)
	}

	// Create rich card message
	message := map[string]interface{}{
		"msg_type": "interactive",
		"card": map[string]interface{}{
			"header": map[string]interface{}{
				"title": map[string]interface{}{
					"tag":     "plain_text",
					"content": title,
				},
				"template": urgencyColor,
			},
			"elements": []interface{}{
				map[string]interface{}{
					"tag": "div",
					"fields": []interface{}{
						map[string]interface{}{
							"is_short": true,
							"text": map[string]interface{}{
								"tag":     "lark_md",
								"content": fmt.Sprintf("**客户名称**\n%s", customerName),
							},
						},
						map[string]interface{}{
							"is_short": true,
							"text": map[string]interface{}{
								"tag":     "lark_md",
								"content": fmt.Sprintf("**紧急程度**\n%s", urgencyLevel),
							},
						},
					},
				},
				map[string]interface{}{
					"tag": "div",
					"fields": []interface{}{
						map[string]interface{}{
							"is_short": false,
							"text": map[string]interface{}{
								"tag":     "lark_md",
								"content": fmt.Sprintf("**试用时间**\n%s", trialPeriod),
							},
						},
					},
				},
				map[string]interface{}{
					"tag": "div",
					"text": map[string]interface{}{
						"tag":     "lark_md",
						"content": fmt.Sprintf("⏰ 该客户的试用期将于 **%s** 到期，请及时跟进！", expiryText),
					},
				},
				map[string]interface{}{
					"tag": "hr",
				},
				map[string]interface{}{
					"tag": "note",
					"elements": []interface{}{
						map[string]interface{}{
							"tag":     "plain_text",
							"content": fmt.Sprintf("发送时间：%s", time.Now().Format("2006-01-02 15:04:05")),
						},
					},
				},
			},
		},
	}

	jsonData, err := json.Marshal(message)
	if err != nil {
		return fmt.Errorf("failed to marshal message: %v", err)
	}

	// Debug: Print the JSON being sent
	log.Printf("DEBUG: Sending Feishu message: %s", string(jsonData))

	resp, err := http.Post(t.feishuWebhook, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("failed to send request: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("feishu API returned status: %d", resp.StatusCode)
	}

	return nil
}

// ExtractEndDate extracts the end date from trial period string for display
func ExtractEndDate(trialStr string) string {
	if trialStr == "" {
		return ""
	}

	// Use regex to extract the end date
	re := regexp.MustCompile(`[～~]\s*(.+)$`)
	matches := re.FindStringSubmatch(trialStr)
	if len(matches) > 1 {
		return strings.TrimSpace(matches[1])
	}

	return trialStr
}
