1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 2//
 3// SPDX-License-Identifier: Apache-2.0
 4
 5package db
 6
 7import (
 8	"database/sql"
 9	"fmt"
10	"sync"
11)
12
13// DeleteProject deletes a project from the database.
14func DeleteProject(db *sql.DB, mu *sync.Mutex, id string) error {
15	mu.Lock()
16	defer mu.Unlock()
17
18	_, err := db.Exec("DELETE FROM projects WHERE id = ?", id)
19	if err != nil {
20		return fmt.Errorf("failed to execute SQL: %w", err)
21	}
22
23	_, err = db.Exec("DELETE FROM releases WHERE project_id = ?", id)
24	if err != nil {
25		return fmt.Errorf("failed to execute SQL: %w", err)
26	}
27
28	return nil
29}
30
31// GetProject returns a project from the database.
32func GetProject(db *sql.DB, id string) (map[string]string, error) {
33	var name, forge, url, version string
34
35	err := db.QueryRow("SELECT name, forge, url, version FROM projects WHERE id = ?", id).Scan(&name, &forge, &url, &version)
36	if err != nil {
37		return nil, fmt.Errorf("failed to scan row: %w", err)
38	}
39
40	project := map[string]string{
41		"id":      id,
42		"name":    name,
43		"url":     url,
44		"forge":   forge,
45		"version": version,
46	}
47
48	return project, nil
49}
50
51// UpsertProject adds or updates a project in the database.
52func UpsertProject(db *sql.DB, mu *sync.Mutex, id, url, name, forge, running string) error {
53	mu.Lock()
54	defer mu.Unlock()
55
56	_, err := db.Exec(`INSERT INTO projects (id, url, name, forge, version)
57		VALUES (?, ?, ?, ?, ?)
58		ON CONFLICT(id) DO 
59			UPDATE SET
60				name = excluded.name,
61				forge = excluded.forge,
62				version = excluded.version;`, id, url, name, forge, running)
63	if err != nil {
64		return fmt.Errorf("failed to execute SQL: %w", err)
65	}
66
67	return nil
68}
69
70// GetProjects returns a list of all projects in the database.
71func GetProjects(db *sql.DB) ([]map[string]string, error) {
72	rows, err := db.Query("SELECT id, name, url, forge, version FROM projects")
73	if err != nil {
74		return nil, fmt.Errorf("failed to query database: %w", err)
75	}
76	defer rows.Close()
77
78	var projects []map[string]string
79	for rows.Next() {
80		var id, name, url, forge, version string
81
82		err = rows.Scan(&id, &name, &url, &forge, &version)
83		if err != nil {
84			return nil, fmt.Errorf("failed to scan row: %w", err)
85		}
86
87		project := map[string]string{
88			"id":      id,
89			"name":    name,
90			"url":     url,
91			"forge":   forge,
92			"version": version,
93		}
94		projects = append(projects, project)
95	}
96
97	return projects, nil
98}