package store

import (
	"database/sql"
	"time"
)

// Environment is a named set of env vars that can be attached to a
// deploy, a sandbox service, or a sandbox's gateway.
type Environment struct {
	ID        string            `json:"id"`
	Name      string            `json:"name"`
	Values    map[string]string `json:"values"`
	CreatedAt int64             `json:"createdAt"`
	UpdatedAt int64             `json:"updatedAt"`
}

// CreateEnvironment persists a new env. Caller assigns id and timestamps.
func (s *Store) CreateEnvironment(e Environment) error {
	now := time.Now().UnixMilli()
	if e.CreatedAt == 0 {
		e.CreatedAt = now
	}
	e.UpdatedAt = now
	json, err := marshalJSON(e.Values)
	if err != nil {
		return err
	}
	_, err = s.db.Exec(
		`INSERT INTO environments(id, name, values_json, created_at, updated_at) VALUES(?,?,?,?,?)`,
		e.ID, e.Name, json, e.CreatedAt, e.UpdatedAt)
	return err
}

// UpdateEnvironment replaces name + values. ErrNotFound if missing.
func (s *Store) UpdateEnvironment(e Environment) error {
	now := time.Now().UnixMilli()
	e.UpdatedAt = now
	json, err := marshalJSON(e.Values)
	if err != nil {
		return err
	}
	res, err := s.db.Exec(
		`UPDATE environments SET name=?, values_json=?, updated_at=? WHERE id=?`,
		e.Name, json, e.UpdatedAt, e.ID)
	if err != nil {
		return err
	}
	n, _ := res.RowsAffected()
	if n == 0 {
		return ErrNotFound
	}
	return nil
}

// GetEnvironment returns one env. ErrNotFound if missing.
func (s *Store) GetEnvironment(id string) (*Environment, error) {
	row := s.db.QueryRow(
		`SELECT id, name, values_json, created_at, updated_at FROM environments WHERE id=?`, id)
	var e Environment
	var raw string
	err := row.Scan(&e.ID, &e.Name, &raw, &e.CreatedAt, &e.UpdatedAt)
	if err == sql.ErrNoRows {
		return nil, ErrNotFound
	}
	if err != nil {
		return nil, err
	}
	v, err := unmarshalJSON(raw)
	if err != nil {
		return nil, err
	}
	e.Values = v
	return &e, nil
}

// ListEnvironments returns all envs, newest first.
func (s *Store) ListEnvironments() ([]Environment, error) {
	rows, err := s.db.Query(
		`SELECT id, name, values_json, created_at, updated_at FROM environments ORDER BY created_at DESC`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var out []Environment
	for rows.Next() {
		var e Environment
		var raw string
		if err := rows.Scan(&e.ID, &e.Name, &raw, &e.CreatedAt, &e.UpdatedAt); err != nil {
			return nil, err
		}
		v, err := unmarshalJSON(raw)
		if err != nil {
			return nil, err
		}
		e.Values = v
		out = append(out, e)
	}
	return out, rows.Err()
}

// DeleteEnvironment removes one env. ErrNotFound if missing.
func (s *Store) DeleteEnvironment(id string) error {
	res, err := s.db.Exec(`DELETE FROM environments WHERE id=?`, id)
	if err != nil {
		return err
	}
	n, _ := res.RowsAffected()
	if n == 0 {
		return ErrNotFound
	}
	return nil
}
