-- ailf.area_scores — one row per area per model per report
--
-- Flattens the nested model_scores array from the Airbyte-loaded raw table
-- into one row per (report, model, area) combination. This is the view that
-- powers per-area trend analysis, model comparison, and cost-effectiveness
-- queries.
--
-- The GROQ projection extracts two arrays from each report:
--   1. model_scores — per-model breakdowns (when multiple models are evaluated)
--   2. fallback_scores — aggregate scores (when only one model or no per-model data)
--
-- This view UNIONs both paths to handle reports with and without per-model data.
--
-- Airbyte loads nested arrays as JSON columns, so we use JSON_QUERY_ARRAY to
-- iterate and JSON_VALUE to extract scalar fields. This is the standard pattern
-- for unnesting Airbyte-loaded nested data in BigQuery.
--
-- Source: ailf_raw.area_scores (Airbyte stream: "area_scores")
-- Target: ailf.area_scores (this view)
--
-- Usage:
--   bq query --use_legacy_sql=false < views/area_scores.sql
--
-- @see docs/design-docs/report-store/bigquery.md

CREATE OR REPLACE VIEW `data-platform-302218.ailf.area_scores` AS

-- Path 1: Reports WITH per-model breakdowns
-- Explodes model_scores[].areas[] into flat rows
SELECT
  r.report_id,
  TIMESTAMP(r.completed_at)                                           AS completed_at,
  r.mode,
  r.source_name,
  JSON_VALUE(area, '$.area')                                          AS area,
  JSON_VALUE(model, '$.model_id')                                     AS model_id,
  ROUND(CAST(JSON_VALUE(area, '$.total_score') AS FLOAT64), 2)        AS total_score,
  ROUND(CAST(JSON_VALUE(area, '$.task_completion') AS FLOAT64), 2)    AS task_completion,
  ROUND(CAST(JSON_VALUE(area, '$.code_correctness') AS FLOAT64), 2)   AS code_correctness,
  ROUND(CAST(JSON_VALUE(area, '$.doc_coverage') AS FLOAT64), 2)       AS doc_coverage,
  ROUND(CAST(COALESCE(JSON_VALUE(area, '$.doc_lift'), JSON_VALUE(area, '$.lift_from_docs')) AS FLOAT64), 2)             AS doc_lift,
  ROUND(CAST(COALESCE(JSON_VALUE(area, '$.ceiling_score'), JSON_VALUE(area, '$.with_docs_score')) AS FLOAT64), 2)     AS ceiling_score,
  ROUND(CAST(COALESCE(JSON_VALUE(area, '$.floor_score'), JSON_VALUE(area, '$.without_docs_score')) AS FLOAT64), 2)    AS floor_score,
  ROUND(CAST(JSON_VALUE(area, '$.total_cost') AS FLOAT64), 4)         AS total_cost,
  CAST(JSON_VALUE(area, '$.test_count') AS INT64)                     AS test_count,
  -- Three-layer decomposition fields (nullable — only present in full-mode reports)
  ROUND(CAST(COALESCE(JSON_VALUE(area, '$.actual_score'), JSON_VALUE(area, '$.actualScore')) AS FLOAT64), 2)       AS actual_score,
  ROUND(CAST(COALESCE(JSON_VALUE(area, '$.retrieval_gap'), JSON_VALUE(area, '$.retrievalGap')) AS FLOAT64), 2)     AS retrieval_gap,
  ROUND(CAST(COALESCE(JSON_VALUE(area, '$.infrastructure_efficiency'), JSON_VALUE(area, '$.infrastructureEfficiency')) AS FLOAT64), 4) AS infrastructure_efficiency
FROM
  `data-platform-302218.ailf_raw.area_scores` AS r,
  UNNEST(JSON_QUERY_ARRAY(r.model_scores)) AS model,
  UNNEST(JSON_QUERY_ARRAY(model, '$.areas')) AS area
WHERE
  r.model_scores IS NOT NULL
  AND JSON_QUERY_ARRAY(r.model_scores) IS NOT NULL

UNION ALL

-- Path 2: Reports WITHOUT per-model breakdowns (fallback to aggregate scores)
-- Uses fallback_model_id as the model identifier
SELECT
  r.report_id,
  TIMESTAMP(r.completed_at)                                            AS completed_at,
  r.mode,
  r.source_name,
  JSON_VALUE(score, '$.area')                                          AS area,
  COALESCE(r.fallback_model_id, 'unknown')                             AS model_id,
  ROUND(CAST(JSON_VALUE(score, '$.total_score') AS FLOAT64), 2)        AS total_score,
  ROUND(CAST(JSON_VALUE(score, '$.task_completion') AS FLOAT64), 2)    AS task_completion,
  ROUND(CAST(JSON_VALUE(score, '$.code_correctness') AS FLOAT64), 2)   AS code_correctness,
  ROUND(CAST(JSON_VALUE(score, '$.doc_coverage') AS FLOAT64), 2)       AS doc_coverage,
  ROUND(CAST(COALESCE(JSON_VALUE(score, '$.doc_lift'), JSON_VALUE(score, '$.lift_from_docs')) AS FLOAT64), 2)             AS doc_lift,
  ROUND(CAST(COALESCE(JSON_VALUE(score, '$.ceiling_score'), JSON_VALUE(score, '$.with_docs_score')) AS FLOAT64), 2)     AS ceiling_score,
  ROUND(CAST(COALESCE(JSON_VALUE(score, '$.floor_score'), JSON_VALUE(score, '$.without_docs_score')) AS FLOAT64), 2)    AS floor_score,
  ROUND(CAST(JSON_VALUE(score, '$.total_cost') AS FLOAT64), 4)         AS total_cost,
  CAST(JSON_VALUE(score, '$.test_count') AS INT64)                     AS test_count,
  -- Three-layer decomposition fields (nullable — only present in full-mode reports)
  ROUND(CAST(COALESCE(JSON_VALUE(score, '$.actual_score'), JSON_VALUE(score, '$.actualScore')) AS FLOAT64), 2)       AS actual_score,
  ROUND(CAST(COALESCE(JSON_VALUE(score, '$.retrieval_gap'), JSON_VALUE(score, '$.retrievalGap')) AS FLOAT64), 2)     AS retrieval_gap,
  ROUND(CAST(COALESCE(JSON_VALUE(score, '$.infrastructure_efficiency'), JSON_VALUE(score, '$.infrastructureEfficiency')) AS FLOAT64), 4) AS infrastructure_efficiency
FROM
  `data-platform-302218.ailf_raw.area_scores` AS r,
  UNNEST(JSON_QUERY_ARRAY(r.fallback_scores)) AS score
WHERE
  r.model_scores IS NULL
  AND r.fallback_scores IS NOT NULL;
