package routes

import (
	"bssapp-backend/auth"
	"bssapp-backend/internal/auditlog"
	"bssapp-backend/internal/security"
	"database/sql"
	"encoding/json"
	"net/http"

	"golang.org/x/crypto/bcrypt"
)

func ChangeOwnPasswordHandler(db *sql.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {

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

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

		// --------------------------------------------------
		// 2️⃣ PAYLOAD
		// --------------------------------------------------
		var req struct {
			CurrentPassword string `json:"current_password"`
			NewPassword     string `json:"new_password"`
		}
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			http.Error(w, "invalid payload", http.StatusBadRequest)
			return
		}

		if req.CurrentPassword == "" || req.NewPassword == "" {
			http.Error(w, "current_password and new_password required", http.StatusBadRequest)
			return
		}

		// --------------------------------------------------
		// 3️⃣ PASSWORD POLICY
		// --------------------------------------------------
		if err := security.ValidatePassword(req.NewPassword); err != nil {
			http.Error(w, err.Error(), http.StatusUnprocessableEntity)
			return
		}

		// --------------------------------------------------
		// 4️⃣ MEVCUT HASH ÇEK
		// --------------------------------------------------
		var currentHash string
		err := db.QueryRow(`
			SELECT password_hash
			FROM mk_dfusr
			WHERE id = $1
			  AND is_active = true
		`, claims.ID).Scan(&currentHash)

		if err != nil {
			http.Error(w, "user not found", http.StatusUnauthorized)
			return
		}

		// --------------------------------------------------
		// 5️⃣ CURRENT PASSWORD CHECK
		// --------------------------------------------------
		if bcrypt.CompareHashAndPassword(
			[]byte(currentHash),
			[]byte(req.CurrentPassword),
		) != nil {
			http.Error(w, "current password incorrect", http.StatusUnauthorized)
			return
		}

		// --------------------------------------------------
		// 6️⃣ NEW HASH
		// --------------------------------------------------
		newHash, err := bcrypt.GenerateFromPassword(
			[]byte(req.NewPassword),
			bcrypt.DefaultCost,
		)
		if err != nil {
			http.Error(w, "hash error", http.StatusInternalServerError)
			return
		}

		// --------------------------------------------------
		// 7️⃣ UPDATE (⚠️ force_password_change DEĞİŞMEZ)
		// --------------------------------------------------
		_, err = db.Exec(`
			UPDATE mk_dfusr
			SET
				password_hash = $1,
				password_updated_at = now(),
				updated_at = now()
			WHERE id = $2
		`, string(newHash), claims.ID)

		if err != nil {
			http.Error(w, "password update failed", http.StatusInternalServerError)
			return
		}

		// --------------------------------------------------
		// 8️⃣ AUDIT
		// --------------------------------------------------
		auditlog.Write(auditlog.ActivityLog{
			ActionType:     "PASSWORD_CHANGED",
			ActionCategory: "security",
			ActionTarget:   claims.Username,
			IsSuccess:      true,
		})

		// --------------------------------------------------
		// 9️⃣ RESPONSE
		// --------------------------------------------------
		_ = json.NewEncoder(w).Encode(map[string]any{
			"success": true,
		})
	}
}
