-- Migration: Fix weekly_report_mv to use max_goal_score for normalized_total_score.
-- Safe to run on DBs where 000020 was not applied (MV still uses max_score, column exists but is NULL).
-- projects_median_mv depends on weekly_report_mv, so we drop and recreate it.

DROP MATERIALIZED VIEW IF EXISTS projects_median_mv;
DROP MATERIALIZED VIEW IF EXISTS weekly_report_mv;

CREATE MATERIALIZED VIEW weekly_report_mv AS
SELECT
    p.id AS project_id,
    agg.report_year,
    agg.report_week,
    COALESCE(agg.total_score, 0.0000) AS total_score,
    CASE
        WHEN wg.max_goal_score IS NULL THEN COALESCE(agg.total_score, 0.0000)
        ELSE LEAST(COALESCE(agg.total_score, 0.0000), wg.max_goal_score)
    END AS normalized_total_score
FROM
    projects p
LEFT JOIN 
    (
        SELECT
            n.project_id,
            EXTRACT(ISOYEAR FROM n.created_date)::INTEGER AS report_year,
            EXTRACT(WEEK FROM n.created_date)::INTEGER AS report_week,
            SUM(n.score) AS total_score
        FROM
            nodes n
        WHERE
            (EXTRACT(ISOYEAR FROM n.created_date)::INTEGER < EXTRACT(ISOYEAR FROM CURRENT_DATE)::INTEGER)
            OR (EXTRACT(ISOYEAR FROM n.created_date)::INTEGER = EXTRACT(ISOYEAR FROM CURRENT_DATE)::INTEGER 
                AND EXTRACT(WEEK FROM n.created_date)::INTEGER < EXTRACT(WEEK FROM CURRENT_DATE)::INTEGER)
        GROUP BY
            1, 2, 3
    ) agg 
    ON p.id = agg.project_id
LEFT JOIN
    weekly_goals wg
    ON wg.project_id = p.id
    AND wg.goal_year = agg.report_year
    AND wg.goal_week = agg.report_week
WHERE
    p.deleted = FALSE
ORDER BY
    p.id, agg.report_year, agg.report_week
WITH DATA;

CREATE INDEX idx_weekly_report_mv_project_year_week 
ON weekly_report_mv(project_id, report_year, report_week);

COMMENT ON MATERIALIZED VIEW weekly_report_mv IS 'Materialized view aggregating weekly scores by project using ISOYEAR for correct week calculations at year boundaries. Includes all projects via LEFT JOIN. Adds normalized_total_score using weekly_goals.max_goal_score. Contains only historical data (excludes current week). Uses nodes.created_date (denormalized) instead of entries.created_date.';

-- Recreate projects_median_mv (depends on weekly_report_mv, last 4 weeks per 000008)
CREATE MATERIALIZED VIEW projects_median_mv AS
SELECT
    p.id AS project_id,
    p.user_id,
    PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY normalized_total_score) AS median_score
FROM (
    SELECT 
        project_id, 
        normalized_total_score,
        report_year,
        report_week,
        ROW_NUMBER() OVER (PARTITION BY project_id ORDER BY report_year DESC, report_week DESC) as rn
    FROM weekly_report_mv
    WHERE 
        (report_year < EXTRACT(ISOYEAR FROM CURRENT_DATE)::INTEGER)
        OR (report_year = EXTRACT(ISOYEAR FROM CURRENT_DATE)::INTEGER 
            AND report_week < EXTRACT(WEEK FROM CURRENT_DATE)::INTEGER)
) sub
JOIN projects p ON p.id = sub.project_id
WHERE rn <= 4 AND p.deleted = FALSE
GROUP BY p.id, p.user_id
WITH DATA;

CREATE INDEX idx_projects_median_mv_project_id ON projects_median_mv(project_id);
CREATE INDEX idx_projects_median_mv_user_id ON projects_median_mv(user_id);

COMMENT ON MATERIALIZED VIEW projects_median_mv IS 'Materialized view calculating median score for each project based on last 4 weeks of historical data. Includes user_id for multi-tenant support.';

ALTER TABLE weekly_goals DROP COLUMN IF EXISTS max_score;
