-- name: ListProjects :many
SELECT * FROM project
WHERE project.workspace_id = $1
  AND (sqlc.narg('space_id')::uuid IS NULL OR EXISTS (
    SELECT 1 FROM project_space pt
    WHERE pt.project_id = project.id
      AND pt.workspace_id = project.workspace_id
      AND pt.space_id = sqlc.narg('space_id')::uuid
  ))
  AND (sqlc.narg('status')::text IS NULL OR project.status = sqlc.narg('status'))
  AND (sqlc.narg('priority')::text IS NULL OR project.priority = sqlc.narg('priority'))
ORDER BY created_at DESC;

-- name: GetProject :one
SELECT * FROM project
WHERE id = $1;

-- name: GetProjectInWorkspace :one
SELECT * FROM project
WHERE id = $1 AND workspace_id = $2;

-- name: CreateProject :one
INSERT INTO project (
    workspace_id, title, description, icon, status,
    lead_type, lead_id, priority
) VALUES (
    $1, $2, $3, $4, $5, $6, $7, $8
) RETURNING *;

-- name: UpdateProject :one
UPDATE project SET
    title = COALESCE(sqlc.narg('title'), title),
    description = sqlc.narg('description'),
    icon = sqlc.narg('icon'),
    status = COALESCE(sqlc.narg('status'), status),
    priority = COALESCE(sqlc.narg('priority'), priority),
    lead_type = sqlc.narg('lead_type'),
    lead_id = sqlc.narg('lead_id'),
    updated_at = now()
WHERE id = $1
RETURNING *;

-- name: DeleteProject :exec
-- Defense-in-depth: workspace_id is a SQL-layer tenant guard. See DeleteIssue.
DELETE FROM project WHERE id = $1 AND workspace_id = $2;

-- name: CountIssuesByProject :one
SELECT count(*) FROM issue
WHERE project_id = $1;

-- name: GetProjectIssueStats :many
SELECT project_id,
       count(*)::bigint AS total_count,
       count(*) FILTER (WHERE status IN ('done', 'cancelled'))::bigint AS done_count
FROM issue
WHERE project_id = ANY(sqlc.arg('project_ids')::uuid[])
GROUP BY project_id;

-- name: ListProjectSpaces :many
SELECT wt.* FROM workspace_space wt
JOIN project_space pt ON pt.space_id = wt.id AND pt.workspace_id = wt.workspace_id
WHERE pt.workspace_id = $1
  AND pt.project_id = $2
ORDER BY wt.name ASC, wt.created_at ASC;

-- name: ListProjectSpacesByProjects :many
SELECT pt.project_id, wt.id, wt.workspace_id, wt.name, wt.key, wt.description,
       wt.icon, wt.issue_counter, wt.archived_at, wt.archived_by,
       wt.created_by, wt.created_at, wt.updated_at
FROM project_space pt
JOIN workspace_space wt ON wt.id = pt.space_id AND wt.workspace_id = pt.workspace_id
WHERE pt.workspace_id = $1
  AND pt.project_id = ANY(sqlc.arg('project_ids')::uuid[])
ORDER BY pt.project_id, wt.name ASC, wt.created_at ASC;

-- name: AddProjectSpace :exec
INSERT INTO project_space (workspace_id, project_id, space_id)
VALUES ($1, $2, $3)
ON CONFLICT (project_id, space_id) DO NOTHING;

-- name: ReplaceProjectSpaces :exec
WITH deleted AS (
  DELETE FROM project_space
  WHERE workspace_id = sqlc.arg('workspace_id')
    AND project_id = sqlc.arg('project_id')
    AND NOT (space_id = ANY(sqlc.arg('space_ids')::uuid[]))
)
INSERT INTO project_space (workspace_id, project_id, space_id)
SELECT sqlc.arg('workspace_id'), sqlc.arg('project_id'), unnest(sqlc.arg('space_ids')::uuid[])
ON CONFLICT (project_id, space_id) DO NOTHING;