package infra

import (
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"time"
)

// SessionValidate busca el token en la tabla sessions, verifica que no este
// expirado y retorna la Session con su metadata deserializada.
// Error si el token no existe, esta expirado o la BD falla.
func SessionValidate(db *sql.DB, token string) (Session, error) {
	var zero Session
	if db == nil {
		return zero, fmt.Errorf("session_validate: db nil")
	}
	if token == "" {
		return zero, fmt.Errorf("session_validate: token vacio")
	}

	var (
		userID    string
		expiresAt int64
		createdAt int64
		metaStr   string
	)
	row := db.QueryRow(
		"SELECT user_id, expires_at, created_at, metadata FROM sessions WHERE token = ?",
		token,
	)
	if err := row.Scan(&userID, &expiresAt, &createdAt, &metaStr); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return zero, fmt.Errorf("session_validate: token no encontrado")
		}
		return zero, fmt.Errorf("session_validate: scan: %w", err)
	}

	if time.Now().Unix() >= expiresAt {
		return zero, fmt.Errorf("session_validate: sesion expirada")
	}

	var metadata map[string]any
	if metaStr != "" {
		if err := json.Unmarshal([]byte(metaStr), &metadata); err != nil {
			return zero, fmt.Errorf("session_validate: metadata malformada: %w", err)
		}
	}

	return Session{
		Token:     token,
		UserID:    userID,
		ExpiresAt: expiresAt,
		CreatedAt: createdAt,
		Metadata:  metadata,
	}, nil
}
