package services

import (
	"context"
	"fmt"

	"github.com/google/uuid"

	"veza-backend-api/internal/database"

	"go.uber.org/zap"
)

// NotificationService handles notification operations
type NotificationService struct {
	db     *database.Database
	logger *zap.Logger
}

// Notification represents a notification
type Notification struct {
	ID        uuid.UUID `json:"id" db:"id"`
	UserID    uuid.UUID `json:"user_id" db:"user_id"`
	Type      string    `json:"type" db:"type"`
	Title     string    `json:"title" db:"title"`
	Content   string    `json:"content" db:"content"`
	Link      string    `json:"link" db:"link"`
	Read      bool      `json:"read" db:"read"`
	CreatedAt string    `json:"created_at" db:"created_at"`
}

// NewNotificationService creates a new notification service
func NewNotificationService(db *database.Database, logger *zap.Logger) *NotificationService {
	return &NotificationService{
		db:     db,
		logger: logger,
	}
}

// CreateNotification creates a new notification
func (ns *NotificationService) CreateNotification(userID uuid.UUID, notificationType, title, content, link string) error {
	ctx := context.Background()

	_, err := ns.db.ExecContext(ctx, `
		INSERT INTO notifications (user_id, type, title, content, link)
		VALUES ($1, $2, $3, $4, $5)
	`, userID, notificationType, title, content, link)

	if err != nil {
		return fmt.Errorf("failed to create notification: %w", err)
	}

	return nil
}

// GetNotifications retrieves notifications for a user
func (ns *NotificationService) GetNotifications(userID uuid.UUID, unreadOnly bool) ([]Notification, error) {
	ctx := context.Background()

	query := `
		SELECT id, user_id, type, title, content, link, read, created_at
		FROM notifications
		WHERE user_id = $1
	`
	args := []interface{}{userID}

	if unreadOnly {
		query += " AND read = FALSE"
	}

	query += " ORDER BY created_at DESC LIMIT 50"

	rows, err := ns.db.QueryContext(ctx, query, args...)
	if err != nil {
		return nil, fmt.Errorf("failed to get notifications: %w", err)
	}
	defer rows.Close()

	var notifications []Notification
	for rows.Next() {
		var notification Notification
		if err := rows.Scan(
			&notification.ID,
			&notification.UserID,
			&notification.Type,
			&notification.Title,
			&notification.Content,
			&notification.Link,
			&notification.Read,
			&notification.CreatedAt,
		); err != nil {
			continue
		}
		notifications = append(notifications, notification)
	}

	return notifications, nil
}

// MarkAsRead marks a notification as read
func (ns *NotificationService) MarkAsRead(userID uuid.UUID, notificationID uuid.UUID) error {
	ctx := context.Background()

	_, err := ns.db.ExecContext(ctx, `
		UPDATE notifications
		SET read = TRUE
		WHERE id = $1 AND user_id = $2
	`, notificationID, userID)

	if err != nil {
		return fmt.Errorf("failed to mark notification as read: %w", err)
	}

	return nil
}

// MarkAllAsRead marks all notifications as read for a user
func (ns *NotificationService) MarkAllAsRead(userID uuid.UUID) error {
	ctx := context.Background()

	_, err := ns.db.ExecContext(ctx, `
		UPDATE notifications
		SET read = TRUE
		WHERE user_id = $1 AND read = FALSE
	`, userID)

	if err != nil {
		return fmt.Errorf("failed to mark all notifications as read: %w", err)
	}

	return nil
}

// GetUnreadCount returns the count of unread notifications
func (ns *NotificationService) GetUnreadCount(userID uuid.UUID) (int, error) {
	ctx := context.Background()

	var count int
	err := ns.db.QueryRowContext(ctx, `
		SELECT COUNT(*)
		FROM notifications
		WHERE user_id = $1 AND read = FALSE
	`, userID).Scan(&count)

	if err != nil {
		return 0, fmt.Errorf("failed to get unread count: %w", err)
	}

	return count, nil
}

// DeleteNotification deletes a notification
func (ns *NotificationService) DeleteNotification(userID uuid.UUID, notificationID uuid.UUID) error {
	ctx := context.Background()

	_, err := ns.db.ExecContext(ctx, `
		DELETE FROM notifications
		WHERE id = $1 AND user_id = $2
	`, notificationID, userID)

	if err != nil {
		return fmt.Errorf("failed to delete notification: %w", err)
	}

	return nil
}

// DeleteAllNotifications deletes all notifications for a user
func (ns *NotificationService) DeleteAllNotifications(userID uuid.UUID) error {
	ctx := context.Background()

	_, err := ns.db.ExecContext(ctx, `
		DELETE FROM notifications
		WHERE user_id = $1
	`, userID)

	if err != nil {
		return fmt.Errorf("failed to delete all notifications: %w", err)
	}

	return nil
}
