package routes

import (
	"bssapp-backend/auth"
	"bssapp-backend/models"
	"bssapp-backend/queries"
	"bssapp-backend/utils"
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"

	"github.com/gorilla/mux"
)

func BulkUpdateOrderLineDueDateHandler(mssql *sql.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json; charset=utf-8")

		claims, ok := auth.GetClaimsFromContext(r.Context())
		if !ok || claims == nil {
			http.Error(w, "unauthorized", http.StatusUnauthorized)
			return
		}

		user := utils.UserFromClaims(claims)
		if user == nil {
			http.Error(w, "Kullanici dogrulanamadi", http.StatusUnauthorized)
			return
		}

		orderHeaderID := mux.Vars(r)["id"]
		if orderHeaderID == "" {
			http.Error(w, "OrderHeaderID bulunamadi", http.StatusBadRequest)
			return
		}

		var payload struct {
			DueDate string `json:"dueDate"`
		}
		if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
			http.Error(w, "Gecersiz JSON", http.StatusBadRequest)
			return
		}

		username := user.Username
		if username == "" {
			username = user.V3Username
		}

		updatedLines, headerUpdated, err := queries.BulkUpdateOrderLineDueDate(mssql, orderHeaderID, payload.DueDate, username)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			_ = json.NewEncoder(w).Encode(map[string]any{
				"code":    "ORDER_BULK_DUE_DATE_UPDATE_FAILED",
				"message": "Siparis satir terminleri guncellenemedi.",
				"detail":  err.Error(),
			})
			return
		}

		_ = json.NewEncoder(w).Encode(map[string]any{
			"success":       true,
			"orderHeaderID": orderHeaderID,
			"dueDate":       payload.DueDate,
			"updatedLines":  updatedLines,
			"headerUpdated": headerUpdated,
		})
	}
}

// ================================
// POST /api/order/update
// ================================
func UpdateOrderHandler(w http.ResponseWriter, r *http.Request) {

	// --------------------------------------------------
	// 1️⃣ JWT CLAIMS (TEK KAYNAK)
	// --------------------------------------------------
	claims, ok := auth.GetClaimsFromContext(r.Context())
	if !ok || claims == nil {
		http.Error(w, "unauthorized", http.StatusUnauthorized)
		return
	}

	user := utils.UserFromClaims(claims)

	if !ok || claims == nil {
		http.Error(w, "Kullanıcı doğrulanamadı", http.StatusUnauthorized)
		return
	}

	user = utils.UserFromClaims(claims)
	if user == nil {
		http.Error(w, "Kullanıcı doğrulanamadı", http.StatusUnauthorized)
		return
	}

	// --------------------------------------------------
	// 2️⃣ REQUEST BODY
	// --------------------------------------------------
	var payload struct {
		Header models.OrderHeader   `json:"header"`
		Lines  []models.OrderDetail `json:"lines"`
	}

	if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
		http.Error(w, "Geçersiz JSON", http.StatusBadRequest)
		return
	}

	// --------------------------------------------------
	// 3️⃣ UPDATE
	// --------------------------------------------------
	results, err := queries.UpdateOrder(
		payload.Header,
		payload.Lines,
		user, // ✅ *models.User
	)

	if err != nil {

		// ✅ VALIDATION ERROR
		var vErr *models.ValidationError
		if errors.As(err, &vErr) {
			w.Header().Set("Content-Type", "application/json")
			w.WriteHeader(http.StatusBadRequest)
			_ = json.NewEncoder(w).Encode(vErr)
			return
		}

		// ❌ SYSTEM ERROR
		utils.LogError("ORDER_UPDATE", err)

		w.WriteHeader(http.StatusInternalServerError)
		_ = json.NewEncoder(w).Encode(map[string]any{
			"code":    "ORDER_UPDATE_FAILED",
			"message": "Sipariş kaydedilirken beklenmeyen bir hata oluştu.",
			"detail":  err.Error(),
		})
		return
	}

	// --------------------------------------------------
	// 4️⃣ RESPONSE
	// --------------------------------------------------
	w.Header().Set("Content-Type", "application/json")
	_ = json.NewEncoder(w).Encode(map[string]any{
		"success": true,
		"lines":   results,
	})
}

// -------------------------------------------------------------
// 🟩 CREATE — /api/order/create
// -------------------------------------------------------------
func CreateOrderHandler(pg *sql.DB, mssql *sql.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {

		w.Header().Set("Content-Type", "application/json; charset=utf-8")

		// --------------------------------------------------
		// JWT CLAIMS (TEK KAYNAK)
		// --------------------------------------------------
		claims, ok := auth.GetClaimsFromContext(r.Context())
		if !ok || claims == nil {
			http.Error(w, "unauthorized", http.StatusUnauthorized)
			return
		}

		user := utils.UserFromClaims(claims)
		if user == nil {
			http.Error(w, "Kullanici dogrulanamadi", http.StatusUnauthorized)
			return
		}

		fmt.Printf("[CREATE] hit user=%s role=%s\n", user.Username, user.RoleCode)

		var payload struct {
			Header models.OrderHeader   `json:"header"`
			Lines  []models.OrderDetail `json:"lines"`
		}

		if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
			fmt.Printf("[CREATE] decode error: %v\n", err)
			http.Error(w, "Gecersiz JSON", http.StatusBadRequest)
			return
		}
		fmt.Printf(
			"[CREATE] payload header_id=%s curr_acc=%s office=%s store=%s orderer_office=%s orderer_store=%s lines=%d\n",
			payload.Header.OrderHeaderID,
			payload.Header.CurrAccCode.String,
			payload.Header.OfficeCode.String,
			payload.Header.StoreCode.String,
			payload.Header.OrdererOfficeCode.String,
			payload.Header.OrdererStoreCode.String,
			len(payload.Lines),
		)
		fmt.Printf(
			"🧾 CREATE PAYLOAD | header_id=%s curr_acc=%s office=%s store=%s orderer_office=%s orderer_store=%s lines=%d\n",
			payload.Header.OrderHeaderID,
			payload.Header.CurrAccCode.String,
			payload.Header.OfficeCode.String,
			payload.Header.StoreCode.String,
			payload.Header.OrdererOfficeCode.String,
			payload.Header.OrdererStoreCode.String,
			len(payload.Lines),
		)

		// --------------------------------------------------
		// INSERT
		// --------------------------------------------------
		newID, lineResults, err := queries.InsertOrder(
			payload.Header,
			payload.Lines,
			user, // *models.User
		)

		if err != nil {

			var vErr *models.ValidationError
			if errors.As(err, &vErr) {
				w.Header().Set("Content-Type", "application/json")
				w.WriteHeader(http.StatusBadRequest)
				_ = json.NewEncoder(w).Encode(vErr)
				return
			}

			// SYSTEM ERROR
			utils.LogError("ORDER_CREATE", err)
			w.WriteHeader(http.StatusInternalServerError)
			_ = json.NewEncoder(w).Encode(map[string]any{
				"code":    "ORDER_CREATE_FAILED",
				"message": "Siparis kaydedilirken beklenmeyen bir hata olustu.",
				"detail":  err.Error(),
			})
			return
		}

		orderNo := ""
		if payload.Header.OrderNumber.Valid {
			orderNo = payload.Header.OrderNumber.String
		}

		// --------------------------------------------------
		// RESPONSE
		// --------------------------------------------------
		_ = json.NewEncoder(w).Encode(map[string]any{
			"status":      "success",
			"orderID":     newID,
			"orderNumber": orderNo,
			"lineResults": lineResults,
		})
	}
}

// -------------------------------------------------------------
// 🟨 GET BY ID — /api/order/get/{id}
// -------------------------------------------------------------
func GetOrderByIDHandler(mssql *sql.DB) http.HandlerFunc {

	return func(w http.ResponseWriter, r *http.Request) {

		w.Header().Set("Content-Type", "application/json; charset=utf-8")

		orderID := mux.Vars(r)["id"]
		if orderID == "" {
			http.Error(w, "Eksik parametre: id", http.StatusBadRequest)
			return
		}

		fmt.Printf("📦 /api/order/get/%s çağrıldı\n", orderID)

		header, lines, err := queries.GetOrderByID(orderID)

		switch {
		case errors.Is(err, sql.ErrNoRows):
			http.Error(w, fmt.Sprintf("Sipariş bulunamadı: %s", orderID), http.StatusNotFound)
			return

		case err != nil:
			http.Error(w, fmt.Sprintf("Veritabanı hatası: %v", err), http.StatusInternalServerError)
			return

		default:
			_ = json.NewEncoder(w).Encode(map[string]any{
				"header": header,
				"lines":  lines,
			})
		}
	}
}

// -------------------------------------------------------------
// 🔎 ORDER EXISTS — /api/order/check/{id}
// -------------------------------------------------------------
func OrderExistsHandler(db *sql.DB) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

		id := mux.Vars(r)["id"]

		var count int
		err := db.QueryRow(`
			SELECT COUNT(*)
			FROM trOrderHeader
			WHERE OrderHeaderID = @p1
		`, id).Scan(&count)

		if err != nil {
			http.Error(w, "db error", http.StatusInternalServerError)
			return
		}

		_ = json.NewEncoder(w).Encode(map[string]any{
			"exists": count > 0,
		})
	})
}
