package data

import (
	"context"
	"database/sql"
	"time"
)

type DeviceToken struct {
	ID        int64     `json:"id"`
	UserID    int64     `json:"user_id"`
	Token     string    `json:"token"`
	CreatedAt time.Time `json:"created_at"`
}

type DeviceTokenModel struct {
	DB *sql.DB
}

func (m DeviceTokenModel) Insert(userID int64, token string) error {
	query := `
		INSERT INTO device_tokens (user_id, token)
		VALUES ($1, $2)
		ON CONFLICT (token) DO UPDATE SET user_id = EXCLUDED.user_id`

	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	_, err := m.DB.ExecContext(ctx, query, userID, token)
	return err
}

func (m DeviceTokenModel) GetForUser(userID int64) ([]DeviceToken, error) {
	query := `SELECT id, user_id, token, created_at FROM device_tokens WHERE user_id = $1`

	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	rows, err := m.DB.QueryContext(ctx, query, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var tokens []DeviceToken
	for rows.Next() {
		var dt DeviceToken
		if err := rows.Scan(&dt.ID, &dt.UserID, &dt.Token, &dt.CreatedAt); err != nil {
			return nil, err
		}
		tokens = append(tokens, dt)
	}
	return tokens, rows.Err()
}

func (m DeviceTokenModel) GetAllTokens() ([]DeviceToken, error) {
	query := `SELECT id, user_id, token, created_at FROM device_tokens`

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	rows, err := m.DB.QueryContext(ctx, query)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var tokens []DeviceToken
	for rows.Next() {
		var dt DeviceToken
		if err := rows.Scan(&dt.ID, &dt.UserID, &dt.Token, &dt.CreatedAt); err != nil {
			return nil, err
		}
		tokens = append(tokens, dt)
	}
	return tokens, rows.Err()
}

func (m DeviceTokenModel) Delete(token string) error {
	query := `DELETE FROM device_tokens WHERE token = $1`

	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	_, err := m.DB.ExecContext(ctx, query, token)
	return err
}
