package handlers

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	"crm-go/internal/storage"
	"crm-go/models"
)

type FollowUpHandler struct {
	storage         storage.FollowUpStorage
	customerStorage storage.CustomerStorage
	feishuWebhook   string
}

func NewFollowUpHandler(storage storage.FollowUpStorage, customerStorage storage.CustomerStorage, feishuWebhook string) *FollowUpHandler {
	return &FollowUpHandler{
		storage:         storage,
		customerStorage: customerStorage,
		feishuWebhook:   feishuWebhook,
	}
}

func (h *FollowUpHandler) GetFollowUps(w http.ResponseWriter, r *http.Request) {
	page := 1
	pageSize := 10

	if pageStr := r.URL.Query().Get("page"); pageStr != "" {
		if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
			page = p
		}
	}

	if pageSizeStr := r.URL.Query().Get("pageSize"); pageSizeStr != "" {
		if ps, err := strconv.Atoi(pageSizeStr); err == nil && ps > 0 {
			pageSize = ps
		}
	}

	followUps, err := h.storage.GetAllFollowUps()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	total := len(followUps)
	totalPages := (total + pageSize - 1) / pageSize

	start := (page - 1) * pageSize
	end := start + pageSize

	if start >= total {
		followUps = []models.FollowUp{}
	} else if end > total {
		followUps = followUps[start:]
	} else {
		followUps = followUps[start:end]
	}

	response := map[string]interface{}{
		"followUps":  followUps,
		"total":      total,
		"page":       page,
		"pageSize":   pageSize,
		"totalPages": totalPages,
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(response)
}

func (h *FollowUpHandler) GetFollowUpByID(w http.ResponseWriter, r *http.Request) {
	urlPath := r.URL.Path
	pathParts := strings.Split(urlPath, "/")

	if len(pathParts) < 4 {
		http.Error(w, "Invalid URL format", http.StatusBadRequest)
		return
	}

	id := pathParts[3]

	if idx := strings.Index(id, "?"); idx != -1 {
		id = id[:idx]
	}

	followUp, err := h.storage.GetFollowUpByID(id)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if followUp == nil {
		http.Error(w, "Follow-up not found", http.StatusNotFound)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(followUp)
}

func (h *FollowUpHandler) CreateFollowUp(w http.ResponseWriter, r *http.Request) {
	var req models.CreateFollowUpRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid request body", http.StatusBadRequest)
		return
	}

	// Parse follow-up time
	followUpTime, err := time.Parse(time.RFC3339, req.FollowUpTime)
	if err != nil {
		http.Error(w, "Invalid follow-up time format", http.StatusBadRequest)
		return
	}

	followUp := models.FollowUp{
		CustomerName:     req.CustomerName,
		DealStatus:       req.DealStatus,
		CustomerLevel:    req.CustomerLevel,
		Industry:         req.Industry,
		FollowUpTime:     followUpTime,
		CreatedAt:        time.Now(),
		NotificationSent: false,
	}

	if err := h.storage.CreateFollowUp(followUp); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(followUp)
}

func (h *FollowUpHandler) UpdateFollowUp(w http.ResponseWriter, r *http.Request) {
	urlPath := r.URL.Path
	pathParts := strings.Split(urlPath, "/")

	if len(pathParts) < 4 {
		http.Error(w, "Invalid URL format", http.StatusBadRequest)
		return
	}

	id := pathParts[3]

	if idx := strings.Index(id, "?"); idx != -1 {
		id = id[:idx]
	}

	var req models.UpdateFollowUpRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid request body", http.StatusBadRequest)
		return
	}

	if err := h.storage.UpdateFollowUp(id, req); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
}

func (h *FollowUpHandler) DeleteFollowUp(w http.ResponseWriter, r *http.Request) {
	urlPath := r.URL.Path
	pathParts := strings.Split(urlPath, "/")

	if len(pathParts) < 4 {
		http.Error(w, "Invalid URL format", http.StatusBadRequest)
		return
	}

	id := pathParts[3]

	if idx := strings.Index(id, "?"); idx != -1 {
		id = id[:idx]
	}

	if err := h.storage.DeleteFollowUp(id); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
}

// SendFeishuNotification sends a notification to Feishu
func (h *FollowUpHandler) SendFeishuNotification(customerName string) error {
	if h.feishuWebhook == "" {
		return fmt.Errorf("Feishu webhook URL not configured")
	}

	// Create Feishu 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": "客户跟进提醒",
				},
				"template": "blue",
			},
			"elements": []map[string]interface{}{
				{
					"tag": "div",
					"text": map[string]interface{}{
						"tag":     "lark_md",
						"content": fmt.Sprintf("<at id=all></at> 请及时跟进 \"%s\"", customerName),
					},
				},
			},
		},
	}

	jsonData, err := json.Marshal(message)
	if err != nil {
		return err
	}

	resp, err := http.Post(h.feishuWebhook, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

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

	return nil
}

// CheckAndSendNotifications checks for pending notifications and sends them
func (h *FollowUpHandler) CheckAndSendNotifications() error {
	pendingFollowUps, err := h.storage.GetPendingNotifications()
	if err != nil {
		return err
	}

	for _, followUp := range pendingFollowUps {
		// Send Feishu notification
		if err := h.SendFeishuNotification(followUp.CustomerName); err != nil {
			fmt.Printf("Error sending notification for follow-up %s: %v\n", followUp.ID, err)
			continue
		}

		// Mark notification as sent
		if err := h.storage.MarkNotificationSent(followUp.ID); err != nil {
			fmt.Printf("Error marking notification as sent for follow-up %s: %v\n", followUp.ID, err)
		}
	}

	return nil
}

// GetCustomerList returns a list of customers with id and name
func (h *FollowUpHandler) GetCustomerList(w http.ResponseWriter, r *http.Request) {
	customers, err := h.customerStorage.GetAllCustomers()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Create a list of customer objects with id and name
	type CustomerInfo struct {
		ID           string `json:"id"`
		CustomerName string `json:"customerName"`
	}

	// Deduplicate by customer name - only show each unique customer name once in dropdown
	// But also create a complete mapping of all customer IDs to names
	seenNames := make(map[string]bool)
	customerMap := make(map[string]string) // All ID -> Name mappings
	var customerList []CustomerInfo        // Deduplicated list for dropdown

	for _, customer := range customers {
		if customer.CustomerName != "" {
			// Add to complete mapping (all records)
			customerMap[customer.ID] = customer.CustomerName

			// Add to deduplicated list (only first occurrence of each name)
			if !seenNames[customer.CustomerName] {
				customerList = append(customerList, CustomerInfo{
					ID:           customer.ID,
					CustomerName: customer.CustomerName,
				})
				seenNames[customer.CustomerName] = true
			}
		}
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"customers":   customerList, // Deduplicated list for dropdown
		"customerMap": customerMap,  // Complete ID->Name mapping for display
	})
}
