package api

import (
	"database/sql"
	"encoding/json"
	"net/http"

	"github.com/syncserver/internal/auth"
)

type AuthHandler struct {
	db *sql.DB
}

func NewAuthHandler(db *sql.DB) *AuthHandler {
	return &AuthHandler{db: db}
}

type LoginRequest struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

type LoginResponse struct {
	User      UserResponse `json:"user"`
	ExpiresAt string       `json:"expires_at"`
}

type UserResponse struct {
	ID       int64  `json:"id"`
	Username string `json:"username"`
	Role     string `json:"role"`
}

func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) {
	var req LoginRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, `{"error":"invalid request"}`, http.StatusBadRequest)
		return
	}

	row := h.db.QueryRow(
		"SELECT id, username, password_hash, role FROM users WHERE username = ?",
		req.Username,
	)
	var u struct {
		ID           int64
		Username     string
		PasswordHash string
		Role         string
	}
	if err := row.Scan(&u.ID, &u.Username, &u.PasswordHash, &u.Role); err != nil {
		http.Error(w, `{"error":"invalid credentials"}`, http.StatusUnauthorized)
		return
	}

	if !auth.VerifyPassword([]byte(u.PasswordHash), req.Password) {
		http.Error(w, `{"error":"invalid credentials"}`, http.StatusUnauthorized)
		return
	}

	jwtMgr := auth.GetJWTManager()
	if jwtMgr == nil {
		http.Error(w, `{"error":"server misconfigured"}`, http.StatusInternalServerError)
		return
	}

	token, expiresAt, err := jwtMgr.Generate(u.ID, u.Username, u.Role)
	if err != nil {
		http.Error(w, `{"error":"failed to generate token"}`, http.StatusInternalServerError)
		return
	}

	auth.SetAuthCookie(w, token, expiresAt)

	resp := LoginResponse{
		User: UserResponse{
			ID:       u.ID,
			Username: u.Username,
			Role:     u.Role,
		},
		ExpiresAt: expiresAt.Format("2006-01-02T15:04:05Z07:00"),
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(resp)
}

func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) {
	auth.ClearAuthCookie(w)
	w.WriteHeader(http.StatusNoContent)
}

func (h *AuthHandler) Me(w http.ResponseWriter, r *http.Request) {
	claims := auth.GetClaims(r.Context())
	if claims == nil {
		http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
		return
	}

	resp := UserResponse{
		ID:       claims.UserID,
		Username: claims.Username,
		Role:     claims.Role,
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{"user": resp})
}
