package repository

import (
	"database/sql"
	"time"

	"aggios-app/backend/internal/domain"

	"github.com/google/uuid"
)

// SubscriptionRepository handles database operations for subscriptions
type SubscriptionRepository struct {
	db *sql.DB
}

// NewSubscriptionRepository creates a new subscription repository
func NewSubscriptionRepository(db *sql.DB) *SubscriptionRepository {
	return &SubscriptionRepository{db: db}
}

// Create creates a new subscription
func (r *SubscriptionRepository) Create(subscription *domain.Subscription) error {
	query := `
		INSERT INTO agency_subscriptions (id, agency_id, plan_id, billing_type, current_users, status, start_date, renewal_date, created_at, updated_at)
		VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
		RETURNING id, created_at, updated_at
	`

	now := time.Now()
	subscription.ID = uuid.New()
	subscription.CreatedAt = now
	subscription.UpdatedAt = now
	subscription.StartDate = now

	// Set renewal date based on billing type
	if subscription.BillingType == "annual" {
		subscription.RenewalDate = now.AddDate(1, 0, 0)
	} else {
		subscription.RenewalDate = now.AddDate(0, 1, 0)
	}

	return r.db.QueryRow(
		query,
		subscription.ID,
		subscription.AgencyID,
		subscription.PlanID,
		subscription.BillingType,
		subscription.CurrentUsers,
		subscription.Status,
		subscription.StartDate,
		subscription.RenewalDate,
		subscription.CreatedAt,
		subscription.UpdatedAt,
	).Scan(&subscription.ID, &subscription.CreatedAt, &subscription.UpdatedAt)
}

// GetByID retrieves a subscription by ID
func (r *SubscriptionRepository) GetByID(id uuid.UUID) (*domain.Subscription, error) {
	query := `
		SELECT id, agency_id, plan_id, billing_type, current_users, status, start_date, renewal_date, created_at, updated_at
		FROM agency_subscriptions
		WHERE id = $1
	`

	subscription := &domain.Subscription{}
	err := r.db.QueryRow(query, id).Scan(
		&subscription.ID,
		&subscription.AgencyID,
		&subscription.PlanID,
		&subscription.BillingType,
		&subscription.CurrentUsers,
		&subscription.Status,
		&subscription.StartDate,
		&subscription.RenewalDate,
		&subscription.CreatedAt,
		&subscription.UpdatedAt,
	)

	return subscription, err
}

// GetByAgencyID retrieves a subscription by agency ID
func (r *SubscriptionRepository) GetByAgencyID(agencyID uuid.UUID) (*domain.Subscription, error) {
	query := `
		SELECT id, agency_id, plan_id, billing_type, current_users, status, start_date, renewal_date, created_at, updated_at
		FROM agency_subscriptions
		WHERE agency_id = $1 AND status = 'active'
		LIMIT 1
	`

	subscription := &domain.Subscription{}
	err := r.db.QueryRow(query, agencyID).Scan(
		&subscription.ID,
		&subscription.AgencyID,
		&subscription.PlanID,
		&subscription.BillingType,
		&subscription.CurrentUsers,
		&subscription.Status,
		&subscription.StartDate,
		&subscription.RenewalDate,
		&subscription.CreatedAt,
		&subscription.UpdatedAt,
	)

	return subscription, err
}

// ListAll retrieves all subscriptions
func (r *SubscriptionRepository) ListAll() ([]*domain.Subscription, error) {
	query := `
		SELECT id, agency_id, plan_id, billing_type, current_users, status, start_date, renewal_date, created_at, updated_at
		FROM agency_subscriptions
		ORDER BY created_at DESC
	`

	rows, err := r.db.Query(query)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var subscriptions []*domain.Subscription

	for rows.Next() {
		subscription := &domain.Subscription{}
		err := rows.Scan(
			&subscription.ID,
			&subscription.AgencyID,
			&subscription.PlanID,
			&subscription.BillingType,
			&subscription.CurrentUsers,
			&subscription.Status,
			&subscription.StartDate,
			&subscription.RenewalDate,
			&subscription.CreatedAt,
			&subscription.UpdatedAt,
		)

		if err != nil {
			return nil, err
		}

		subscriptions = append(subscriptions, subscription)
	}

	return subscriptions, rows.Err()
}

// Update updates a subscription
func (r *SubscriptionRepository) Update(subscription *domain.Subscription) error {
	query := `
		UPDATE agency_subscriptions
		SET plan_id = $2, billing_type = $3, current_users = $4, status = $5, renewal_date = $6, updated_at = $7
		WHERE id = $1
		RETURNING updated_at
	`

	subscription.UpdatedAt = time.Now()

	return r.db.QueryRow(
		query,
		subscription.ID,
		subscription.PlanID,
		subscription.BillingType,
		subscription.CurrentUsers,
		subscription.Status,
		subscription.RenewalDate,
		subscription.UpdatedAt,
	).Scan(&subscription.UpdatedAt)
}

// Delete deletes a subscription
func (r *SubscriptionRepository) Delete(id uuid.UUID) error {
	query := `DELETE FROM agency_subscriptions WHERE id = $1`
	result, err := r.db.Exec(query, id)
	if err != nil {
		return err
	}

	rowsAffected, err := result.RowsAffected()
	if err != nil {
		return err
	}

	if rowsAffected == 0 {
		return sql.ErrNoRows
	}

	return nil
}

// UpdateUserCount updates the current user count for a subscription
func (r *SubscriptionRepository) UpdateUserCount(agencyID uuid.UUID, userCount int) error {
	query := `
		UPDATE agency_subscriptions
		SET current_users = $2, updated_at = $3
		WHERE agency_id = $1 AND status = 'active'
	`

	_, err := r.db.Exec(query, agencyID, userCount, time.Now())
	return err
}
