-- address_audit_report.sql
-- Post-run report for the address-mismatch audit (issue #582 Phase 1).
--
-- Sections:
--   1. Summary — count, p50/p75/p95/mean distance, % street_differs,
--      % over 50m / 200m thresholds.
--   2. Top-20 outliers by distance (manual triage list).
--   3. Per-district breakdown — same metrics grouped by district column.
--
-- Run via psql:
--   psql "$DATABASE_URL" -v batch='2026-05-25_run1' -f scripts/address_audit_report.sql
--
-- :batch is a psql client variable substituted via -v.

\set ON_ERROR_STOP on

\echo '=============================================='
\echo ' Address mismatch audit — batch:' :batch
\echo '=============================================='

-- ---------------------------------------------------------------------------
-- 1) Top-level summary
-- ---------------------------------------------------------------------------
\echo ''
\echo '--- Summary (status=ok rows only) ---'
SELECT
    COUNT(*)                                                      AS n_total,
    COUNT(*) FILTER (WHERE audit_status = 'ok')                   AS n_ok,
    COUNT(*) FILTER (WHERE audit_status = 'no_match')             AS n_no_match,
    COUNT(*) FILTER (WHERE audit_status = 'error')                AS n_error,
    COUNT(*) FILTER (WHERE audit_status = 'blocked')              AS n_blocked,
    ROUND(percentile_cont(0.50)
          WITHIN GROUP (ORDER BY distance_m)::numeric, 1)         AS p50_distance_m,
    ROUND(percentile_cont(0.75)
          WITHIN GROUP (ORDER BY distance_m)::numeric, 1)         AS p75_distance_m,
    ROUND(percentile_cont(0.95)
          WITHIN GROUP (ORDER BY distance_m)::numeric, 1)         AS p95_distance_m,
    ROUND(AVG(distance_m)::numeric, 1)                            AS mean_distance_m,
    ROUND(100.0 * AVG(CASE WHEN street_differs THEN 1.0 ELSE 0.0 END), 1)
                                                                   AS pct_street_differs,
    ROUND(100.0 * AVG(CASE WHEN distance_m > 50  THEN 1.0 ELSE 0.0 END), 1)
                                                                   AS pct_over_50m,
    ROUND(100.0 * AVG(CASE WHEN distance_m > 200 THEN 1.0 ELSE 0.0 END), 1)
                                                                   AS pct_over_200m
FROM address_mismatch_audit
WHERE audit_batch = :'batch'
  AND audit_status = 'ok';

-- ---------------------------------------------------------------------------
-- 2) Top-20 outliers
-- ---------------------------------------------------------------------------
\echo ''
\echo '--- Top-20 outliers by distance ---'
SELECT
    house_id,
    district,
    ROUND(distance_m::numeric, 1)   AS distance_m,
    street_differs,
    LEFT(original_address, 60)      AS original_address,
    LEFT(snapped_address, 60)       AS snapped_address
FROM address_mismatch_audit
WHERE audit_batch = :'batch'
  AND audit_status = 'ok'
  AND distance_m IS NOT NULL
ORDER BY distance_m DESC NULLS LAST
LIMIT 20;

-- ---------------------------------------------------------------------------
-- 3) Per-district breakdown
-- ---------------------------------------------------------------------------
\echo ''
\echo '--- Per-district breakdown (status=ok only) ---'
SELECT
    COALESCE(district, '(no district)')                            AS district,
    COUNT(*)                                                       AS n,
    ROUND(percentile_cont(0.50)
          WITHIN GROUP (ORDER BY distance_m)::numeric, 1)          AS p50_distance_m,
    ROUND(percentile_cont(0.95)
          WITHIN GROUP (ORDER BY distance_m)::numeric, 1)          AS p95_distance_m,
    ROUND(AVG(distance_m)::numeric, 1)                             AS mean_distance_m,
    ROUND(100.0 * AVG(CASE WHEN street_differs THEN 1.0 ELSE 0.0 END), 1)
                                                                    AS pct_street_differs,
    ROUND(100.0 * AVG(CASE WHEN distance_m > 50  THEN 1.0 ELSE 0.0 END), 1)
                                                                    AS pct_over_50m,
    ROUND(100.0 * AVG(CASE WHEN distance_m > 200 THEN 1.0 ELSE 0.0 END), 1)
                                                                    AS pct_over_200m
FROM address_mismatch_audit
WHERE audit_batch = :'batch'
  AND audit_status = 'ok'
GROUP BY COALESCE(district, '(no district)')
ORDER BY n DESC, district;
