// routes/password_reset_complete.go
package routes

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

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

func CompletePasswordResetHandler(db *sql.DB) http.HandlerFunc {

	type request struct {
		Token    string `json:"token"`
		Password string `json:"password"`
	}

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

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

		var req request
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.Token == "" || req.Password == "" {
			http.Error(w, "invalid payload", http.StatusBadRequest)
			return
		}

		if err := security.ValidatePassword(req.Password); err != nil {
			http.Error(w, err.Error(), http.StatusUnprocessableEntity)
			return
		}

		tokenHash := security.HashToken(req.Token)

		// 1) token doğrula
		var userID int64
		var expiresAt time.Time

		err := db.QueryRow(`
			SELECT dfusr_id, expires_at
			FROM dfusr_password_reset
			WHERE token_hash = $1
			  AND used_at IS NULL
		`, tokenHash).Scan(&userID, &expiresAt)

		if err != nil || time.Now().After(expiresAt) {
			http.Error(w, "invalid or expired token", http.StatusUnprocessableEntity)
			return
		}

		// 2) yeni hash
		passHash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
		if err != nil {
			http.Error(w, "hash error", http.StatusInternalServerError)
			return
		}

		// 3) tx: şifre + used_at
		tx, err := db.Begin()
		if err != nil {
			http.Error(w, "tx error", http.StatusInternalServerError)
			return
		}
		defer tx.Rollback()

		// mk_dfusr güncelle
		if _, err := tx.Exec(`
			UPDATE mk_dfusr
			SET password_hash = $1,
			    force_password_change = false,
			    password_updated_at = now(),
			    updated_at = now()
			WHERE id = $2
		`, string(passHash), userID); err != nil {
			http.Error(w, "update failed", http.StatusInternalServerError)
			return
		}

		// token tüket
		if _, err := tx.Exec(`
			UPDATE dfusr_password_reset
			SET used_at = now()
			WHERE token_hash = $1
			  AND used_at IS NULL
		`, tokenHash); err != nil {
			http.Error(w, "token update failed", http.StatusInternalServerError)
			return
		}

		if err := tx.Commit(); err != nil {
			http.Error(w, "commit failed", http.StatusInternalServerError)
			return
		}

		// 4) refresh revoke
		_ = repository.NewRefreshTokenRepository(db).RevokeAllForUser(userID)

		// 5) user + perms + jwt
		mkRepo := repository.NewMkUserRepository(db)
		u, err := mkRepo.GetByID(userID)
		if err != nil {
			http.Error(w, "user fetch failed", http.StatusInternalServerError)
			return
		}

		permRepo := repository.NewPermissionRepository(db)
		perms, _ := permRepo.GetPermissionsByRoleID(u.RoleID)

		// ✅ CLAIMS BUILD
		claims := auth.BuildClaimsFromUser(u, 15*time.Minute)

		// ✅ TOKEN
		jwtStr, err := auth.GenerateToken(
			claims,
			u.Username,
			false,
		)
		if err != nil {
			http.Error(w, "token generation failed", http.StatusInternalServerError)
			return
		}

		auditlog.Write(auditlog.ActivityLog{
			ActionType:     "PASSWORD_RESET_COMPLETED",
			ActionCategory: "security",
			ActionTarget:   u.Username,
			IsSuccess:      true,
		})

		_ = json.NewEncoder(w).Encode(map[string]any{
			"success": true,
			"token":   jwtStr,
			"user": map[string]any{
				"id":                    u.ID,
				"username":              u.Username,
				"email":                 u.Email,
				"is_active":             u.IsActive,
				"role_id":               u.RoleID,
				"role_code":             u.RoleCode,
				"force_password_change": false,
				"v3_username":           u.V3Username,
				"v3_usergroup":          u.V3UserGroup,
			},
			"permissions": perms,
		})
	}
}
