package routes

import (
	"bssapp-backend/internal/auditlog"
	"bssapp-backend/internal/mailer"
	"bssapp-backend/internal/security"
	"bssapp-backend/models"
	"bssapp-backend/queries"
	"bytes"
	"database/sql"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/gorilla/mux"
)

// ======================================================
// 👤 USER DETAIL ROUTE (GET + PUT)
// URL: /api/users/{id}
// ======================================================
type LoginUser struct {
	ID                  int64  `json:"id"`
	Username            string `json:"username"`
	Email               string `json:"email"`
	RoleID              int    `json:"role_id"`
	RoleCode            string `json:"role_code"`
	ForcePasswordChange bool   `json:"force_password_change"`
}

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

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

		idStr := mux.Vars(r)["id"]
		userID, err := strconv.ParseInt(idStr, 10, 64)
		if err != nil || userID <= 0 {
			http.Error(w, "Geçersiz kullanıcı id", http.StatusBadRequest)
			return
		}

		switch r.Method {
		case http.MethodGet:
			handleUserGet(db, w, userID)
		case http.MethodPut:
			handleUserUpdate(db, w, r, userID)
		case http.MethodOptions:
			w.WriteHeader(http.StatusOK)
		default:
			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		}
	})
}

// ======================================================
// 📥 GET USER
// ======================================================
// ======================================================
// 📥 GET USER (FINAL - mk_dfusr Uyumlu)
// ======================================================
func handleUserGet(db *sql.DB, w http.ResponseWriter, userID int64) {

	var u models.UserDetail

	// --------------------------------------------------
	// 🟢 HEADER
	// --------------------------------------------------
	err := db.QueryRow(
		queries.GetUserHeader,
		userID,
	).Scan(
		&u.ID,
		&u.Code, // username
		&u.IsActive,
		&u.FullName,
		&u.Email,
		&u.Mobile,
		&u.Address,
		&u.HasPassword,
	)

	if err != nil {

		// detaylı log (çok önemli)
		fmt.Println("❌ [UserDetail] HEADER SCAN ERROR:", err)

		if err == sql.ErrNoRows {
			http.Error(w, "Kullanıcı bulunamadı", http.StatusNotFound)
			return
		}

		http.Error(w, "User header error", http.StatusInternalServerError)
		return
	}

	// --------------------------------------------------
	// 🟢 ROLES
	// --------------------------------------------------
	roleRows, err := db.Query(queries.GetUserRoles, userID)
	if err != nil {
		fmt.Println("⚠️ [UserDetail] ROLE QUERY:", err)
	} else {
		defer roleRows.Close()

		for roleRows.Next() {
			var code string

			if err := roleRows.Scan(&code); err == nil {
				u.Roles = append(u.Roles, code)
			}
		}
	}

	// --------------------------------------------------
	// 🟢 DEPARTMENTS
	// --------------------------------------------------
	deptRows, err := db.Query(queries.GetUserDepartments, userID)
	if err != nil {
		fmt.Println("⚠️ [UserDetail] DEPT QUERY:", err)
	} else {
		defer deptRows.Close()

		for deptRows.Next() {

			var d models.DeptOption

			if err := deptRows.Scan(&d.Code, &d.Title); err == nil {
				u.Departments = append(u.Departments, d)
			}
		}
	}

	// --------------------------------------------------
	// 🟢 PIYASALAR
	// --------------------------------------------------
	piyRows, err := db.Query(queries.GetUserPiyasalar, userID)
	if err != nil {
		fmt.Println("⚠️ [UserDetail] PIYASA QUERY:", err)
	} else {
		defer piyRows.Close()

		for piyRows.Next() {

			var p models.DeptOption

			if err := piyRows.Scan(&p.Code, &p.Title); err == nil {
				u.Piyasalar = append(u.Piyasalar, p)
			}
		}
	}

	// --------------------------------------------------
	// 🟢 NEBIM USERS
	// --------------------------------------------------
	nebimRows, err := db.Query(queries.GetUserNebim, userID)
	if err != nil {
		fmt.Println("⚠️ [UserDetail] NEBIM QUERY:", err)
	} else {
		defer nebimRows.Close()

		for nebimRows.Next() {

			var n models.NebimOption

			if err := nebimRows.Scan(
				&n.Username,
				&n.UserGroupCode,
			); err == nil {

				u.NebimUsers = append(u.NebimUsers, n)
			}
		}
	}

	// --------------------------------------------------
	// 🟢 RESPONSE
	// --------------------------------------------------
	w.WriteHeader(http.StatusOK)

	if err := json.NewEncoder(w).Encode(u); err != nil {
		fmt.Println("❌ [UserDetail] JSON ENCODE:", err)
	}
}

// ======================================================
// ✍️ UPDATE USER (PUT)
// ======================================================
func handleUserUpdate(db *sql.DB, w http.ResponseWriter, r *http.Request, userID int64) {

	raw, _ := io.ReadAll(r.Body)

	fmt.Println("🟥 RAW BODY:", string(raw))

	// body tekrar okunabilsin diye reset
	r.Body = io.NopCloser(bytes.NewBuffer(raw))

	var payload models.UserWrite

	if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
		fmt.Printf("🟦 DECODED PAYLOAD: %+v\n", payload)

		fmt.Println("❌ JSON DECODE ERROR:", err)

		http.Error(w, "Geçersiz payload", http.StatusBadRequest)
		return
	}

	tx, err := db.Begin()
	if err != nil {
		http.Error(w, "Transaction başlatılamadı", http.StatusInternalServerError)
		return
	}
	defer tx.Rollback()

	_, err = tx.Exec(
		queries.UpdateUserHeader,
		userID,
		payload.Code,
		payload.IsActive,
		payload.FullName,
		payload.Email,
		payload.Mobile,
		payload.Address,
	)
	if err != nil {
		http.Error(w, "Header güncellenemedi", http.StatusInternalServerError)
		return
	}

	tx.Exec(`DELETE FROM dfrole_usr WHERE dfusr_id = $1`, userID)
	for _, code := range payload.Roles {
		tx.Exec(queries.InsertUserRole, userID, code)
	}

	tx.Exec(`DELETE FROM dfusr_dprt WHERE dfusr_id = $1`, userID)
	for _, d := range payload.Departments {
		tx.Exec(queries.InsertUserDepartment, userID, d.Code)
	}

	tx.Exec(`DELETE FROM dfusr_piyasa WHERE dfusr_id = $1`, userID)
	for _, p := range payload.Piyasalar {
		tx.Exec(queries.InsertUserPiyasa, userID, p.Code)
	}

	tx.Exec(`DELETE FROM dfusr_nebim_user WHERE dfusr_id = $1`, userID)
	for _, n := range payload.NebimUsers {
		tx.Exec(queries.InsertUserNebim, userID, n.Username)
	}

	if err := tx.Commit(); err != nil {
		http.Error(w, "Commit başarısız", http.StatusInternalServerError)
		return
	}

	_ = json.NewEncoder(w).Encode(map[string]any{"success": true})
}

// ======================================================
// 🔐 ADMIN — PASSWORD RESET MAIL
// ======================================================
func SendPasswordResetMailHandler(
	db *sql.DB,
	mailer *mailer.GraphMailer,
) http.HandlerFunc {

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

		userID, _ := strconv.ParseInt(mux.Vars(r)["id"], 10, 64)

		var email string
		err := db.QueryRow(`
				SELECT email
				FROM mk_dfusr
				WHERE id = $1 AND is_active = true
			`, userID).Scan(&email)

		if err != nil || email == "" {
			w.WriteHeader(http.StatusOK)
			return
		}

		// 🔑 TOKEN (PLAIN + HASH)
		plain, hash, err := security.GenerateResetToken()
		if err != nil {
			w.WriteHeader(http.StatusOK)
			return
		}

		expires := time.Now().Add(30 * time.Minute)

		// 💾 DB → SADECE HASH
		_, _ = db.Exec(`
			INSERT INTO dfusr_password_reset (dfusr_id, token, expires_at)
			VALUES ($1,$2,$3)
		`, userID, hash, expires)

		// 🔗 URL → PLAIN
		resetURL := fmt.Sprintf(
			"%s/password-reset/%s",
			os.Getenv("FRONTEND_URL"),
			plain,
		)

		_ = mailer.SendPasswordResetMail(email, resetURL)

		// 🕵️ AUDIT
		auditlog.ForcePasswordChangeStarted(
			r.Context(),
			userID,
			"admin_reset",
		)

		w.WriteHeader(http.StatusOK)
	}
}
