package inventory

import (
	"context"
	"fmt"
	"time"

	"royal-pop-backend/internal/database"
)

type Level struct {
	Style          string
	ColorwayID     string
	FinishID       string
	QuantityOnHand int64
	Notes          string
	CreatedAt      time.Time
	UpdatedAt      time.Time
}

type UpsertInput struct {
	Style          string
	ColorwayID     string
	FinishID       string
	QuantityOnHand int64
	Notes          string
}

type Store struct {
	db *database.DB
}

func NewStore(db *database.DB) *Store {
	return &Store{db: db}
}

func (s *Store) List(ctx context.Context) ([]Level, error) {
	if s == nil || s.db == nil || s.db.Pool == nil {
		return nil, fmt.Errorf("postgres store is not configured")
	}

	rows, err := s.db.Pool.Query(ctx, `
		SELECT style, colorway_id, finish_id, quantity_on_hand, notes, created_at, updated_at
		FROM inventory_levels
		ORDER BY style ASC, colorway_id ASC, finish_id ASC
	`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	levels := make([]Level, 0)
	for rows.Next() {
		var level Level
		if err := rows.Scan(
			&level.Style,
			&level.ColorwayID,
			&level.FinishID,
			&level.QuantityOnHand,
			&level.Notes,
			&level.CreatedAt,
			&level.UpdatedAt,
		); err != nil {
			return nil, err
		}
		levels = append(levels, level)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	return levels, nil
}

func (s *Store) Upsert(ctx context.Context, input UpsertInput) (*Level, error) {
	if s == nil || s.db == nil || s.db.Pool == nil {
		return nil, fmt.Errorf("postgres store is not configured")
	}

	row := s.db.Pool.QueryRow(ctx, `
		INSERT INTO inventory_levels (style, colorway_id, finish_id, quantity_on_hand, notes)
		VALUES ($1, $2, $3, $4, $5)
		ON CONFLICT (style, colorway_id, finish_id)
		DO UPDATE SET
			quantity_on_hand = EXCLUDED.quantity_on_hand,
			notes = EXCLUDED.notes,
			updated_at = NOW()
		RETURNING style, colorway_id, finish_id, quantity_on_hand, notes, created_at, updated_at
	`, input.Style, input.ColorwayID, input.FinishID, input.QuantityOnHand, input.Notes)

	var level Level
	if err := row.Scan(
		&level.Style,
		&level.ColorwayID,
		&level.FinishID,
		&level.QuantityOnHand,
		&level.Notes,
		&level.CreatedAt,
		&level.UpdatedAt,
	); err != nil {
		return nil, err
	}

	return &level, nil
}
