1use rusqlite::params;
2
3use super::StateStore;
4use super::types::PendingDecision;
5use crate::errors::Result;
6
7impl StateStore {
8 pub fn upsert_pending_decision(
11 &self,
12 source: &str,
13 resource: &str,
14 tier: &str,
15 action: &str,
16 summary: &str,
17 ) -> Result<i64> {
18 let timestamp = crate::utc_now_iso8601();
19 let updated = self.conn.execute(
21 "UPDATE pending_decisions SET tier = ?1, action = ?2, summary = ?3, created_at = ?4
22 WHERE source = ?5 AND resource = ?6 AND resolved_at IS NULL",
23 params![tier, action, summary, timestamp, source, resource],
24 )?;
25
26 if updated > 0 {
27 let id = self
28 .conn
29 .query_row(
30 "SELECT id FROM pending_decisions WHERE source = ?1 AND resource = ?2 AND resolved_at IS NULL",
31 params![source, resource],
32 |row| row.get(0),
33 )
34 ?;
35 return Ok(id);
36 }
37
38 self.conn.execute(
39 "INSERT INTO pending_decisions (source, resource, tier, action, summary, created_at)
40 VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
41 params![source, resource, tier, action, summary, timestamp],
42 )?;
43 Ok(self.conn.last_insert_rowid())
44 }
45
46 pub fn pending_decisions(&self) -> Result<Vec<PendingDecision>> {
48 let mut stmt = self
49 .conn
50 .prepare(
51 "SELECT id, source, resource, tier, action, summary, created_at, resolved_at, resolution
52 FROM pending_decisions WHERE resolved_at IS NULL ORDER BY created_at DESC",
53 )
54 ?;
55
56 let rows = stmt
57 .query_map([], |row| {
58 Ok(PendingDecision {
59 id: row.get(0)?,
60 source: row.get(1)?,
61 resource: row.get(2)?,
62 tier: row.get(3)?,
63 action: row.get(4)?,
64 summary: row.get(5)?,
65 created_at: row.get(6)?,
66 resolved_at: row.get(7)?,
67 resolution: row.get(8)?,
68 })
69 })?
70 .collect::<std::result::Result<Vec<_>, _>>()?;
71
72 Ok(rows)
73 }
74
75 pub fn pending_decisions_for_source(&self, source: &str) -> Result<Vec<PendingDecision>> {
77 let mut stmt = self
78 .conn
79 .prepare(
80 "SELECT id, source, resource, tier, action, summary, created_at, resolved_at, resolution
81 FROM pending_decisions WHERE source = ?1 AND resolved_at IS NULL ORDER BY created_at DESC",
82 )
83 ?;
84
85 let rows = stmt
86 .query_map(params![source], |row| {
87 Ok(PendingDecision {
88 id: row.get(0)?,
89 source: row.get(1)?,
90 resource: row.get(2)?,
91 tier: row.get(3)?,
92 action: row.get(4)?,
93 summary: row.get(5)?,
94 created_at: row.get(6)?,
95 resolved_at: row.get(7)?,
96 resolution: row.get(8)?,
97 })
98 })?
99 .collect::<std::result::Result<Vec<_>, _>>()?;
100
101 Ok(rows)
102 }
103
104 pub fn resolve_decision(&self, resource: &str, resolution: &str) -> Result<bool> {
106 let timestamp = crate::utc_now_iso8601();
107 let updated = self.conn.execute(
108 "UPDATE pending_decisions SET resolved_at = ?1, resolution = ?2
109 WHERE resource = ?3 AND resolved_at IS NULL",
110 params![timestamp, resolution, resource],
111 )?;
112 Ok(updated > 0)
113 }
114
115 pub fn resolve_decisions_for_source(&self, source: &str, resolution: &str) -> Result<usize> {
117 let timestamp = crate::utc_now_iso8601();
118 let updated = self.conn.execute(
119 "UPDATE pending_decisions SET resolved_at = ?1, resolution = ?2
120 WHERE source = ?3 AND resolved_at IS NULL",
121 params![timestamp, resolution, source],
122 )?;
123 Ok(updated)
124 }
125
126 pub fn resolve_all_decisions(&self, resolution: &str) -> Result<usize> {
128 let timestamp = crate::utc_now_iso8601();
129 let updated = self.conn.execute(
130 "UPDATE pending_decisions SET resolved_at = ?1, resolution = ?2
131 WHERE resolved_at IS NULL",
132 params![timestamp, resolution],
133 )?;
134 Ok(updated)
135 }
136}