package store

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

func (s *Store) ListAPIKeys(ctx context.Context) ([]APIKey, error) {
	rows, err := s.db.QueryContext(ctx, `
		SELECT id, name, key_prefix, enabled, last_used_at, created_at
		FROM api_keys
		ORDER BY id DESC`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return scanAPIKeys(rows)
}

func (s *Store) CreateAPIKey(ctx context.Context, name, keyPrefix, keyHash string) (*APIKey, error) {
	res, err := s.db.ExecContext(ctx, `
		INSERT INTO api_keys(name, key_prefix, key_hash, enabled)
		VALUES(?,?,?,1)`, name, keyPrefix, keyHash)
	if err != nil {
		return nil, err
	}
	id, _ := res.LastInsertId()
	return s.GetAPIKey(ctx, id)
}

func (s *Store) GetAPIKey(ctx context.Context, id int64) (*APIKey, error) {
	row := s.db.QueryRowContext(ctx, `
		SELECT id, name, key_prefix, enabled, last_used_at, created_at
		FROM api_keys WHERE id=?`, id)
	return scanAPIKey(row)
}

func (s *Store) DeleteAPIKey(ctx context.Context, id int64) error {
	_, err := s.db.ExecContext(ctx, `DELETE FROM api_keys WHERE id=?`, id)
	return err
}

func (s *Store) VerifyAPIKey(ctx context.Context, keyHash string) (bool, error) {
	var id int64
	err := s.db.QueryRowContext(ctx, `
		SELECT id FROM api_keys WHERE key_hash=? AND enabled=1`, keyHash).Scan(&id)
	if err == sql.ErrNoRows {
		return false, nil
	}
	if err != nil {
		return false, err
	}
	_, _ = s.db.ExecContext(ctx, `UPDATE api_keys SET last_used_at=datetime('now') WHERE id=?`, id)
	return true, nil
}

func scanAPIKeys(rows *sql.Rows) ([]APIKey, error) {
	var out []APIKey
	for rows.Next() {
		item, err := scanAPIKeyFromRows(rows)
		if err != nil {
			return nil, err
		}
		out = append(out, *item)
	}
	return out, rows.Err()
}

func scanAPIKey(row *sql.Row) (*APIKey, error) {
	var item APIKey
	var enabled int
	var lastUsed, created sql.NullString
	if err := row.Scan(&item.ID, &item.Name, &item.KeyPrefix, &enabled, &lastUsed, &created); err != nil {
		return nil, err
	}
	item.Enabled = enabled == 1
	if lastUsed.Valid {
		if t, err := time.Parse("2006-01-02 15:04:05", lastUsed.String); err == nil {
			item.LastUsedAt = &t
		}
	}
	if created.Valid {
		if t, err := time.Parse("2006-01-02 15:04:05", created.String); err == nil {
			item.CreatedAt = t
		}
	}
	return &item, nil
}

func scanAPIKeyFromRows(rows *sql.Rows) (*APIKey, error) {
	var item APIKey
	var enabled int
	var lastUsed, created sql.NullString
	if err := rows.Scan(&item.ID, &item.Name, &item.KeyPrefix, &enabled, &lastUsed, &created); err != nil {
		return nil, err
	}
	item.Enabled = enabled == 1
	if lastUsed.Valid {
		if t, err := time.Parse("2006-01-02 15:04:05", lastUsed.String); err == nil {
			item.LastUsedAt = &t
		}
	}
	if created.Valid {
		if t, err := time.Parse("2006-01-02 15:04:05", created.String); err == nil {
			item.CreatedAt = t
		}
	}
	return &item, nil
}
