package main

import (
	"database/sql"
	"embed"
	"fmt"

	"fn-registry/functions/infra"
)

//go:embed migrations/*.sql
var migrationsFS embed.FS

type DB struct{ conn *sql.DB }

func openDB(path string) (*DB, error) {
	conn, err := infra.SQLiteOpen(path, "")
	if err != nil {
		return nil, err
	}
	if err := infra.ApplyMigrations(conn, migrationsFS, "migrations/*.sql"); err != nil {
		conn.Close()
		return nil, fmt.Errorf("migrate: %w", err)
	}
	return &DB{conn: conn}, nil
}

func (d *DB) Close() error { return d.conn.Close() }

type tableCount struct {
	Name string
	Rows int64
}

func (d *DB) tableCounts() ([]tableCount, error) {
	tables := []string{"sessions", "calls", "code_writes", "test_runs", "e2e_runs_fn", "violations", "patterns", "function_versions", "copied_code", "function_sequences"}
	out := make([]tableCount, 0, len(tables))
	for _, t := range tables {
		var n int64
		if err := d.conn.QueryRow("SELECT COUNT(*) FROM " + t).Scan(&n); err != nil {
			return nil, fmt.Errorf("count %s: %w", t, err)
		}
		out = append(out, tableCount{Name: t, Rows: n})
	}
	return out, nil
}

type funcStat struct {
	FunctionID      string
	CallsTotal      int64
	Calls7d         int64
	ErrorsTotal     int64
	ErrorRate       float64
	MeanDurationMs  float64
	LastUsedAt      sql.NullInt64
}

func (d *DB) topFunctions(limit int) ([]funcStat, error) {
	rows, err := d.conn.Query(`
		SELECT function_id, calls_total, calls_7d, errors_total, error_rate, mean_duration_ms, last_used_at
		FROM function_stats
		ORDER BY calls_total DESC
		LIMIT ?`, limit)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var out []funcStat
	for rows.Next() {
		var s funcStat
		if err := rows.Scan(&s.FunctionID, &s.CallsTotal, &s.Calls7d, &s.ErrorsTotal, &s.ErrorRate, &s.MeanDurationMs, &s.LastUsedAt); err != nil {
			return nil, err
		}
		out = append(out, s)
	}
	return out, rows.Err()
}
