-- =============================================================================
-- CRUD PATTERNS — Sáng kiến application system
-- =============================================================================

-- =============================================================================
-- CREATE: Submit a new application with multiple authors (atomic)
-- =============================================================================
BEGIN;
  -- Set audit context
  SELECT set_config('my.user_id', '42', true);

  -- 1. Main record
  INSERT INTO applications(code, title, registration_year, status, purpose,
                           is_technical_solution, primary_unit_id, created_by)
  VALUES ('SK-2025-007',
          'Hệ thống tự động điền hồ sơ sáng kiến',
          2025, 'DRAFT',
          'Tự động hoá việc điền các mẫu số 01–04',
          TRUE, 2, 42)
  RETURNING application_id \gset

  -- 2. Authors (defer contribution-sum check until COMMIT)
  SET CONSTRAINTS trg_contribution_total DEFERRED;
  INSERT INTO application_authors(application_id, user_id, contribution_pct, role, display_order) VALUES
    (:application_id, 42, 60.00, 'PRIMARY',    1),
    (:application_id, 13, 25.00, 'CO_AUTHOR',  2),
    (:application_id, 27, 15.00, 'CO_AUTHOR',  3);

  -- 3. Orgs that tested it
  INSERT INTO application_adopters(application_id, org_name, address, field) VALUES
    (:application_id, 'Phòng KHCN', '217 Hồng Bàng, Q.5', 'Cải cách hành chính');
COMMIT;


-- =============================================================================
-- READ: Dashboard — paginated list with filters
-- =============================================================================
SELECT * FROM v_application_summary
 WHERE registration_year = 2025
   AND status = ANY(ARRAY['UNDER_REVIEW','EVALUATED']::text[])
   AND title ILIKE '%động vật%'              -- uses trigram index
 ORDER BY avg_score DESC NULLS LAST, submitted_at DESC
 LIMIT 20 OFFSET 0;

-- Read: full application with nested data (app layer usually does this as N queries
-- or one JSON aggregate — here's the aggregate version)
SELECT jsonb_build_object(
  'application', to_jsonb(a.*),
  'authors',     (SELECT jsonb_agg(jsonb_build_object(
                    'user_id', u.user_id,
                    'name',    u.full_name,
                    'pct',     aa.contribution_pct,
                    'role',    aa.role
                  ) ORDER BY aa.display_order)
                  FROM application_authors aa
                  JOIN users u USING (user_id)
                  WHERE aa.application_id = a.application_id),
  'evaluations',(SELECT jsonb_agg(to_jsonb(e.*))
                  FROM evaluations e WHERE e.application_id = a.application_id),
  'attachments',(SELECT jsonb_agg(to_jsonb(att.*))
                  FROM attachments att WHERE att.application_id = a.application_id)
) AS document
FROM applications a
WHERE a.application_id = 1 AND a.deleted_at IS NULL;

-- Full-text search (Vietnamese-friendly; combine with unaccent for better recall)
SELECT application_id, code, title
  FROM applications
 WHERE to_tsvector('simple', title || ' ' || coalesce(introduction,''))
    @@ plainto_tsquery('simple', 'đạo đức động vật')
 ORDER BY registration_year DESC
 LIMIT 10;


-- =============================================================================
-- UPDATE: Progress an application through the workflow
-- =============================================================================
-- Submit (DRAFT → SUBMITTED). Triggers populate submitted_at automatically.
UPDATE applications SET status = 'SUBMITTED' WHERE application_id = 7;

-- Assign to review panel
UPDATE applications SET status = 'UNDER_REVIEW' WHERE application_id = 7;

-- Upsert an evaluation (same evaluator re-scores)
INSERT INTO evaluations (application_id, evaluator_id, novelty_score, effectiveness_score, conclusion)
VALUES (7, 99, 32, 48, 'Đề nghị công nhận')
ON CONFLICT (application_id, evaluator_id)
DO UPDATE SET
    novelty_score       = EXCLUDED.novelty_score,
    effectiveness_score = EXCLUDED.effectiveness_score,
    conclusion          = EXCLUDED.conclusion,
    evaluated_at        = NOW();

-- Update JSONB field: patch a single effectiveness sub-field
UPDATE applications
   SET effectiveness = effectiveness || jsonb_build_object(
       'economic',
       'Tiết kiệm ~30% thời gian xét duyệt'
   )
 WHERE application_id = 7;

-- Partial update (PATCH-style) — only update provided fields. The app layer
-- generates SET clauses from the non-null fields in the request body.
UPDATE applications
   SET title   = COALESCE($1, title),
       purpose = COALESCE($2, purpose),
       updated_at = NOW()
 WHERE application_id = $3 AND deleted_at IS NULL
RETURNING *;


-- =============================================================================
-- DELETE: Soft delete + restore
-- =============================================================================
-- Soft delete
UPDATE applications SET deleted_at = NOW() WHERE application_id = 7;

-- Restore
UPDATE applications SET deleted_at = NULL WHERE application_id = 7;

-- Hard delete (only for drafts, cascades to authors/evaluations/etc.)
DELETE FROM applications
 WHERE application_id = 7
   AND status = 'DRAFT';


-- =============================================================================
-- ANALYTICS: Materialized-view refresh (run nightly via cron/pgAgent)
-- =============================================================================
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_annual_stats;

-- Leaderboard: top-scoring approved innovations
SELECT code, title, avg_score
  FROM v_application_summary
 WHERE status = 'APPROVED'
 ORDER BY avg_score DESC
 LIMIT 10;
