package handlers

import (
	"database/sql"
	"encoding/json"
	"furry-sos-backend/config"
	"net/http"
)

// ============================================
// 📋 ดึงรายการเคสที่รออนุมัติ (ระดมทุน)
// ============================================

func GetPendingFundraising(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	query := `SELECT 
		sc.share_id, 
		sc.user_id, 
		sc.report_id, 
		sc.report_type, 
		sc.share_title, 
		sc.share_description, 
		sc.fundraising_goal, 
		sc.fundraising_bank_account, 
		sc.created_at,
		u.full_name AS user_name,
		u.phone AS user_phone
		FROM shared_cases sc
		JOIN users u ON sc.user_id = u.user_id
		WHERE sc.is_fundraising = TRUE AND sc.is_approved = FALSE 
		ORDER BY sc.created_at DESC`

	rows, err := config.DB.Query(query)
	if err != nil {
		http.Error(w, "Failed to get pending cases: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	var cases []map[string]interface{}
	for rows.Next() {
		var shareID, userID, reportID int
		var reportType, shareTitle, shareDescription string
		var goal sql.NullFloat64
		var bankAccount sql.NullString
		var createdAt string
		var userName, userPhone string

		err := rows.Scan(
			&shareID, &userID, &reportID, &reportType, &shareTitle,
			&shareDescription, &goal, &bankAccount, &createdAt,
			&userName, &userPhone,
		)
		if err != nil {
			continue
		}

		c := make(map[string]interface{})
		c["share_id"] = shareID
		c["user_id"] = userID
		c["report_id"] = reportID
		c["report_type"] = reportType
		c["share_title"] = shareTitle
		c["share_description"] = shareDescription
		c["created_at"] = createdAt
		c["user_name"] = userName
		c["user_phone"] = userPhone

		c["fundraising_goal"] = 0.0
		if goal.Valid {
			c["fundraising_goal"] = goal.Float64
		}

		c["bank_account"] = ""
		if bankAccount.Valid {
			c["bank_account"] = bankAccount.String
		}

		var animalType string
		if reportType == "emergency" {
			config.DB.QueryRow(`SELECT animal_type FROM emergency_reports WHERE report_id = ?`, reportID).Scan(&animalType)
		} else {
			config.DB.QueryRow(`SELECT animal_type FROM deceased_reports WHERE report_id = ?`, reportID).Scan(&animalType)
		}
		c["animal_type"] = animalType

		cases = append(cases, c)
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(cases)
}

func ApproveFundraising(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	var req map[string]interface{}
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		http.Error(w, "Invalid JSON: "+err.Error(), http.StatusBadRequest)
		return
	}

	shareIDFloat, ok := req["share_id"].(float64)
	if !ok {
		http.Error(w, "Missing share_id", http.StatusBadRequest)
		return
	}
	shareID := int(shareIDFloat)

	adminIDFloat, ok := req["admin_id"].(float64)
	if !ok {
		http.Error(w, "Missing admin_id", http.StatusBadRequest)
		return
	}
	adminID := int(adminIDFloat)

	query := `UPDATE shared_cases SET 
	          is_approved = TRUE, 
	          approved_by = ?, 
	          approved_at = NOW()
	          WHERE share_id = ?`

	_, err = config.DB.Exec(query, adminID, shareID)
	if err != nil {
		http.Error(w, "Failed to approve: "+err.Error(), http.StatusInternalServerError)
		return
	}

	var userID int
	config.DB.QueryRow(`SELECT user_id FROM shared_cases WHERE share_id = ?`, shareID).Scan(&userID)

	createNotificationsTable()
	notifyQuery := `INSERT INTO notifications 
	                (user_id, title, message, notification_type, reference_id, created_at) 
	                VALUES (?, ?, ?, 'fundraising', ?, NOW())`
	config.DB.Exec(notifyQuery, userID,
		"✅ เคสของคุณได้รับการอนุมัติแล้ว!",
		"เคสของคุณได้รับการอนุมัติให้ระดมทุนได้แล้ว คุณสามารถแชร์เคสนี้เพื่อรับบริจาคได้เลย!",
		shareID)

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"message":  "✅ อนุมัติเคสสำเร็จ!",
		"share_id": shareID,
	})
}

func RejectFundraising(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	var req map[string]interface{}
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		http.Error(w, "Invalid JSON: "+err.Error(), http.StatusBadRequest)
		return
	}

	shareIDFloat, ok := req["share_id"].(float64)
	if !ok {
		http.Error(w, "Missing share_id", http.StatusBadRequest)
		return
	}
	shareID := int(shareIDFloat)

	reason, _ := req["reason"].(string)
	if reason == "" {
		reason = "ไม่ผ่านเงื่อนไขการระดมทุน"
	}

	query := `UPDATE shared_cases SET is_fundraising = FALSE WHERE share_id = ?`
	_, err = config.DB.Exec(query, shareID)
	if err != nil {
		http.Error(w, "Failed to reject: "+err.Error(), http.StatusInternalServerError)
		return
	}

	var userID int
	config.DB.QueryRow(`SELECT user_id FROM shared_cases WHERE share_id = ?`, shareID).Scan(&userID)

	createNotificationsTable()
	notifyQuery := `INSERT INTO notifications 
	                (user_id, title, message, notification_type, reference_id, created_at) 
	                VALUES (?, ?, ?, 'system', ?, NOW())`
	config.DB.Exec(notifyQuery, userID,
		"❌ เคสของคุณถูกปฏิเสธ",
		"เคสของคุณไม่ได้รับอนุมัติให้ระดมทุน เหตุผล: "+reason,
		shareID)

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"message":  "✅ ปฏิเสธเคสสำเร็จ!",
		"share_id": shareID,
	})
}

func CheckFundraisingApproval(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	reportID := r.URL.Query().Get("report_id")
	if reportID == "" {
		http.Error(w, "Missing report_id", http.StatusBadRequest)
		return
	}

	var shareID sql.NullInt64
	var isFundraising, isApproved bool
	var approvedAt sql.NullTime

	reportType := r.URL.Query().Get("type")
	if reportType == "" {
		reportType = "emergency"
	}

	query := `SELECT share_id, is_fundraising, is_approved, approved_at 
	          FROM shared_cases 
	          WHERE report_id = ? AND report_type = ? 
	          ORDER BY created_at DESC LIMIT 1`

	err := config.DB.QueryRow(query, reportID, reportType).Scan(
		&shareID, &isFundraising, &isApproved, &approvedAt,
	)

	if err != nil {
		if err == sql.ErrNoRows {
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(map[string]interface{}{
				"share_id":       nil,
				"is_fundraising": false,
				"is_approved":    false,
				"message":        "ไม่พบข้อมูล",
			})
			return
		}
		http.Error(w, "Database error: "+err.Error(), http.StatusInternalServerError)
		return
	}

	approvedAtStr := ""
	if approvedAt.Valid {
		approvedAtStr = approvedAt.Time.Format("2006-01-02 15:04:05")
	}

	shareIDVal := 0
	if shareID.Valid {
		shareIDVal = int(shareID.Int64)
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"share_id":       shareIDVal,
		"is_fundraising": isFundraising,
		"is_approved":    isApproved,
		"approved_at":    approvedAtStr,
	})
}

func GetAdminStats(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	var totalUsers, totalReports, pendingReports, totalVolunteers int
	var totalFundraising, approvedFundraising, pendingFundraising int

	config.DB.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&totalUsers)
	config.DB.QueryRow(`SELECT COUNT(*) FROM volunteers`).Scan(&totalVolunteers)
	config.DB.QueryRow(`SELECT COUNT(*) FROM emergency_reports`).Scan(&totalReports)
	config.DB.QueryRow(`SELECT COUNT(*) FROM emergency_reports WHERE status = 'pending' OR status = 'assigned'`).Scan(&pendingReports)
	config.DB.QueryRow(`SELECT COUNT(*) FROM shared_cases WHERE is_fundraising = TRUE`).Scan(&totalFundraising)
	config.DB.QueryRow(`SELECT COUNT(*) FROM shared_cases WHERE is_fundraising = TRUE AND is_approved = TRUE`).Scan(&approvedFundraising)

	pendingFundraising = totalFundraising - approvedFundraising

	stats := map[string]interface{}{
		"total_users":          totalUsers,
		"total_volunteers":     totalVolunteers,
		"total_reports":        totalReports,
		"pending_reports":      pendingReports,
		"total_fundraising":    totalFundraising,
		"approved_fundraising": approvedFundraising,
		"pending_fundraising":  pendingFundraising,
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(stats)
}

func GetSystemBankAccount(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	createSettingsTable()

	var bankName, bankAccount, accountHolder, qrCodeURL string

	query := `SELECT setting_key, setting_value FROM system_settings 
	          WHERE setting_key IN ('bank_name', 'bank_account', 'account_holder', 'qr_code_url')`
	rows, err := config.DB.Query(query)
	if err != nil {
		http.Error(w, "Failed to get settings: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	for rows.Next() {
		var key, value string
		rows.Scan(&key, &value)
		switch key {
		case "bank_name":
			bankName = value
		case "bank_account":
			bankAccount = value
		case "account_holder":
			accountHolder = value
		case "qr_code_url":
			qrCodeURL = value
		}
	}

	if bankName == "" {
		bankName = "ธนาคารกรุงไทย"
		bankAccount = "123-4-56789-0"
		accountHolder = "มูลนิธิ Furry SOS"
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"bank_name":      bankName,
		"bank_account":   bankAccount,
		"account_holder": accountHolder,
		"qr_code_url":    qrCodeURL,
	})
}

func createNotificationsTable() {
	query := `CREATE TABLE IF NOT EXISTS notifications (
		notification_id INT PRIMARY KEY AUTO_INCREMENT,
		user_id INT NOT NULL,
		title VARCHAR(200) NOT NULL,
		message TEXT NOT NULL,
		is_read BOOLEAN DEFAULT FALSE,
		notification_type ENUM('fundraising', 'system', 'approval') DEFAULT 'system',
		reference_id INT DEFAULT NULL,
		created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
		INDEX idx_notifications_user_id (user_id),
		INDEX idx_notifications_is_read (is_read)
	)`
	config.DB.Exec(query)
}

func createSettingsTable() {
	query := `CREATE TABLE IF NOT EXISTS system_settings (
		setting_id INT PRIMARY KEY AUTO_INCREMENT,
		setting_key VARCHAR(50) UNIQUE NOT NULL,
		setting_value TEXT,
		updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
	)`
	config.DB.Exec(query)

	config.DB.Exec(`INSERT IGNORE INTO system_settings (setting_key, setting_value) VALUES 
		('bank_name', 'ธนาคารกรุงไทย'),
		('bank_account', '123-4-56789-0'),
		('account_holder', 'มูลนิธิ Furry SOS'),
		('qr_code_url', 'https://example.com/qr/furry-sos.jpg')`)
}

func GetUserNotifications(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	userID := r.URL.Query().Get("user_id")
	if userID == "" {
		http.Error(w, "Missing user_id", http.StatusBadRequest)
		return
	}

	query := `SELECT notification_id, title, message, is_read, notification_type, created_at 
	          FROM notifications WHERE user_id = ? ORDER BY created_at DESC LIMIT 50`

	rows, err := config.DB.Query(query, userID)
	if err != nil {
		http.Error(w, "Failed to get notifications: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	var notifications []map[string]interface{}
	for rows.Next() {
		var id int
		var title, message, notifType, createdAt string
		var isRead bool
		rows.Scan(&id, &title, &message, &isRead, &notifType, &createdAt)
		notifications = append(notifications, map[string]interface{}{
			"notification_id": id,
			"title":           title,
			"message":         message,
			"is_read":         isRead,
			"type":            notifType,
			"created_at":      createdAt,
		})
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(notifications)
}

func MarkNotificationRead(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	var req map[string]interface{}
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		http.Error(w, "Invalid JSON", http.StatusBadRequest)
		return
	}

	notifIDFloat, ok := req["notification_id"].(float64)
	if !ok {
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"success": false,
			"message": "notification_id ไม่ถูกต้อง",
		})
		return
	}
	notifID := int(notifIDFloat)
	query := `UPDATE notifications SET is_read = TRUE WHERE notification_id = ?`
	_, err = config.DB.Exec(query, notifID)
	if err != nil {
		http.Error(w, "Failed to mark as read: "+err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"message": "✅ อ่านแล้ว",
	})
}
