package routes

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

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

func FirstPasswordChangeHandler(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, "password fields required", http.StatusUnprocessableEntity)
			return
		}

		// --------------------------------------------------
		// 3️⃣ LOAD USER (mk_dfusr)
		// --------------------------------------------------
		var currentHash string
		err := db.QueryRow(`
			SELECT password_hash
			FROM mk_dfusr
			WHERE id = $1
		`, claims.ID).Scan(&currentHash)

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

		// --------------------------------------------------
		// 4️⃣ CURRENT PASSWORD CHECK
		// --------------------------------------------------
		if bcrypt.CompareHashAndPassword(
			[]byte(currentHash),
			[]byte(req.CurrentPassword),
		) != nil {
			http.Error(w, "mevcut şifre hatalı", http.StatusUnauthorized)
			return
		}

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

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

		// --------------------------------------------------
		// 7️⃣ UPDATE mk_dfusr
		// --------------------------------------------------
		_, err = db.Exec(`
			UPDATE mk_dfusr
			SET
				password_hash = $1,
				force_password_change = false,
				password_updated_at = NOW(),
				updated_at = NOW()
			WHERE id = $2
		`, string(hash), claims.ID)

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

		// --------------------------------------------------
		// 8️⃣ REFRESH TOKEN REVOKE
		// --------------------------------------------------
		_ = repository.
			NewRefreshTokenRepository(db).
			RevokeAllForUser(claims.ID)

		// --------------------------------------------------
		// 9️⃣ NEW JWT (TEK DOĞRU YOL)
		// --------------------------------------------------
		newClaims := auth.BuildClaimsFromUser(
			&models.MkUser{
				ID:                  claims.ID,
				Username:            claims.Username,
				RoleCode:            claims.RoleCode,
				V3Username:          claims.V3Username,
				V3UserGroup:         claims.V3UserGroup,
				SessionID:           claims.SessionID,
				ForcePasswordChange: false,
			},
			15*time.Minute,
		)

		newToken, err := auth.GenerateToken(
			newClaims,
			claims.Username,
			false,
		)
		if err != nil {
			http.Error(w, "token generation failed", http.StatusInternalServerError)
			return
		}

		// --------------------------------------------------
		// 🔟 AUDIT
		// --------------------------------------------------
		auditlog.ForcePasswordChangeCompleted(
			r.Context(),
			claims.ID,
			"self_change",
		)

		// --------------------------------------------------
		// 1️⃣1️⃣ RESPONSE
		// --------------------------------------------------
		_ = json.NewEncoder(w).Encode(map[string]any{
			"token": newToken,
			"user": map[string]any{
				"id":                    claims.ID,
				"username":              claims.Username,
				"force_password_change": false,
			},
		})
		log.Printf("✅ FIRST-PASS claims user=%d role=%s", claims.ID, claims.RoleCode)
	}
}
