SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

CREATE OR ALTER PROCEDURE dbo.SceneMetricType_ProjectHasMetrics
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT CAST(CASE WHEN EXISTS
    (
        SELECT 1
        FROM dbo.ProjectTimelineMetricSettings ptms
        INNER JOIN dbo.SceneMetricTypes mt ON mt.MetricTypeID = ptms.MetricTypeID
        WHERE ptms.ProjectID = @ProjectID AND mt.IsActive = 1
    ) THEN 1 ELSE 0 END AS bit);
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneMetricType_AddMissingDefaultsForProject
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;

    IF NOT EXISTS (SELECT 1 FROM dbo.ProjectTimelineSettings WHERE ProjectID = @ProjectID)
    BEGIN
        INSERT dbo.ProjectTimelineSettings
            (ProjectID, ShowSceneCards, ShowMetricShape, ShowPlotLines, ShowStoryAssets, ShowCharacterAppearances, ShowWarnings)
        VALUES
            (@ProjectID, 1, 1, 1, 1, 1, 1);
    END;

    INSERT dbo.ProjectTimelineMetricSettings (ProjectID, MetricTypeID, SortOrder)
    SELECT @ProjectID, mt.MetricTypeID, mt.SortOrder
    FROM dbo.SceneMetricTypes mt
    WHERE mt.ProjectID IS NULL
        AND mt.IsActive = 1
        AND mt.MetricName IN
        (
            N'Overall Intensity', N'Tension', N'Emotional Weight', N'Action', N'Darkness',
            N'Romance', N'Sexual Charge', N'Violence', N'Hope / Lightness', N'Comedy', N'Mystery'
        )
        AND NOT EXISTS
        (
            SELECT 1
            FROM dbo.ProjectTimelineMetricSettings ptms
            INNER JOIN dbo.SceneMetricTypes existing ON existing.MetricTypeID = ptms.MetricTypeID
            WHERE ptms.ProjectID = @ProjectID
                AND LOWER(existing.MetricName) = LOWER(mt.MetricName)
        );
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneMetricType_ListForProjectManagement
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;

    ;WITH CandidateMetrics AS
    (
        SELECT mt.*
        FROM dbo.SceneMetricTypes mt
        WHERE mt.ProjectID = @ProjectID
        UNION
        SELECT mt.*
        FROM dbo.SceneMetricTypes mt
        WHERE mt.ProjectID IS NULL
            AND mt.MetricName IN
            (
                N'Overall Intensity', N'Tension', N'Emotional Weight', N'Action', N'Darkness',
                N'Romance', N'Sexual Charge', N'Violence', N'Hope / Lightness', N'Comedy', N'Mystery'
            )
        UNION
        SELECT mt.*
        FROM dbo.SceneMetricTypes mt
        INNER JOIN dbo.ProjectTimelineMetricSettings ptms ON ptms.MetricTypeID = mt.MetricTypeID
        WHERE ptms.ProjectID = @ProjectID
    )
    SELECT cm.MetricTypeID, cm.ProjectID, cm.MetricName, cm.Description, cm.MinValue, cm.MaxValue, cm.DefaultValue,
        COALESCE(ptms.SortOrder, cm.SortOrder) AS SortOrder,
        CAST(CASE WHEN cm.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 1 ELSE 0 END AS bit) AS IsActive,
        CAST(CASE WHEN cm.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 1 ELSE 0 END AS bit) AS IsEnabledForProject,
        COUNT(smv.SceneID) AS ValueCount
    FROM CandidateMetrics cm
    LEFT JOIN dbo.ProjectTimelineMetricSettings ptms ON ptms.ProjectID = @ProjectID AND ptms.MetricTypeID = cm.MetricTypeID
    LEFT JOIN dbo.SceneMetricValues smv ON smv.MetricTypeID = cm.MetricTypeID
    GROUP BY cm.MetricTypeID, cm.ProjectID, cm.MetricName, cm.Description, cm.MinValue, cm.MaxValue, cm.DefaultValue,
        cm.SortOrder, cm.IsActive, ptms.MetricTypeID, ptms.SortOrder
    ORDER BY
        CASE WHEN cm.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 0 ELSE 1 END,
        COALESCE(ptms.SortOrder, cm.SortOrder),
        cm.MetricName;
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneMetricType_GetForProject
    @MetricTypeID int,
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT mt.MetricTypeID, mt.ProjectID, mt.MetricName, mt.Description, mt.MinValue, mt.MaxValue, mt.DefaultValue,
        COALESCE(ptms.SortOrder, mt.SortOrder) AS SortOrder,
        CAST(CASE WHEN mt.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 1 ELSE 0 END AS bit) AS IsActive,
        CAST(CASE WHEN mt.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 1 ELSE 0 END AS bit) AS IsEnabledForProject,
        (SELECT COUNT(*) FROM dbo.SceneMetricValues smv WHERE smv.MetricTypeID = mt.MetricTypeID) AS ValueCount
    FROM dbo.SceneMetricTypes mt
    LEFT JOIN dbo.ProjectTimelineMetricSettings ptms ON ptms.ProjectID = @ProjectID AND ptms.MetricTypeID = mt.MetricTypeID
    WHERE mt.MetricTypeID = @MetricTypeID
        AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID);
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneMetricType_SaveForProject
    @MetricTypeID int = NULL,
    @ProjectID int,
    @MetricName nvarchar(100),
    @Description nvarchar(500) = NULL,
    @MinValue int,
    @MaxValue int,
    @DefaultValue int,
    @SortOrder int,
    @IsActive bit = 1
AS
BEGIN
    SET NOCOUNT ON;

    IF @MinValue >= @MaxValue
        THROW 50010, 'Metric minimum must be less than maximum.', 1;

    IF @DefaultValue < @MinValue OR @DefaultValue > @MaxValue
        THROW 50011, 'Metric default value must be inside the metric range.', 1;

    IF @MetricTypeID IS NULL OR @MetricTypeID = 0
    BEGIN
        SELECT @MetricTypeID = MetricTypeID
        FROM dbo.SceneMetricTypes
        WHERE ProjectID = @ProjectID AND LOWER(MetricName) = LOWER(@MetricName);

        IF @MetricTypeID IS NULL OR @MetricTypeID = 0
        BEGIN
            INSERT dbo.SceneMetricTypes (ProjectID, MetricName, Description, MinValue, MaxValue, DefaultValue, SortOrder, IsActive)
            VALUES (@ProjectID, @MetricName, @Description, @MinValue, @MaxValue, @DefaultValue, @SortOrder, 1);
            SET @MetricTypeID = CAST(SCOPE_IDENTITY() AS int);
        END
    END

    UPDATE dbo.SceneMetricTypes
    SET MetricName = @MetricName,
        Description = @Description,
        MinValue = @MinValue,
        MaxValue = @MaxValue,
        DefaultValue = @DefaultValue,
        SortOrder = @SortOrder,
        IsActive = 1
    WHERE MetricTypeID = @MetricTypeID
        AND (ProjectID = @ProjectID OR ProjectID IS NULL);

    IF @IsActive = 1
    BEGIN
        MERGE dbo.ProjectTimelineMetricSettings AS target
        USING (SELECT @ProjectID AS ProjectID, @MetricTypeID AS MetricTypeID, @SortOrder AS SortOrder) AS source
        ON target.ProjectID = source.ProjectID AND target.MetricTypeID = source.MetricTypeID
        WHEN MATCHED THEN UPDATE SET SortOrder = source.SortOrder
        WHEN NOT MATCHED THEN INSERT (ProjectID, MetricTypeID, SortOrder) VALUES (source.ProjectID, source.MetricTypeID, source.SortOrder);
    END
    ELSE
    BEGIN
        DELETE FROM dbo.ProjectTimelineMetricSettings WHERE ProjectID = @ProjectID AND MetricTypeID = @MetricTypeID;
    END;

    SELECT @MetricTypeID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneMetricType_SetActiveForProject
    @MetricTypeID int,
    @ProjectID int,
    @IsActive bit
AS
BEGIN
    SET NOCOUNT ON;

    IF @IsActive = 1
    BEGIN
        UPDATE dbo.SceneMetricTypes
        SET IsActive = 1
        WHERE MetricTypeID = @MetricTypeID
            AND ProjectID = @ProjectID;

        INSERT dbo.ProjectTimelineMetricSettings (ProjectID, MetricTypeID, SortOrder)
        SELECT @ProjectID, mt.MetricTypeID, mt.SortOrder
        FROM dbo.SceneMetricTypes mt
        WHERE mt.MetricTypeID = @MetricTypeID
            AND mt.IsActive = 1
            AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
            AND NOT EXISTS
            (
                SELECT 1 FROM dbo.ProjectTimelineMetricSettings ptms
                WHERE ptms.ProjectID = @ProjectID AND ptms.MetricTypeID = @MetricTypeID
            );

        SELECT CAST(CASE WHEN EXISTS
        (
            SELECT 1
            FROM dbo.ProjectTimelineMetricSettings ptms
            INNER JOIN dbo.SceneMetricTypes mt ON mt.MetricTypeID = ptms.MetricTypeID
            WHERE ptms.ProjectID = @ProjectID
                AND ptms.MetricTypeID = @MetricTypeID
                AND mt.IsActive = 1
                AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
        ) THEN 1 ELSE 0 END AS bit);
        RETURN;
    END
    ELSE
    BEGIN
        DELETE FROM dbo.ProjectTimelineMetricSettings
        WHERE ProjectID = @ProjectID AND MetricTypeID = @MetricTypeID;

        UPDATE dbo.SceneMetricTypes
        SET IsActive = 0
        WHERE MetricTypeID = @MetricTypeID AND ProjectID = @ProjectID;

        SELECT CAST(CASE WHEN NOT EXISTS
        (
            SELECT 1
            FROM dbo.ProjectTimelineMetricSettings
            WHERE ProjectID = @ProjectID AND MetricTypeID = @MetricTypeID
        ) THEN 1 ELSE 0 END AS bit);
        RETURN;
    END;
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneMetricType_MoveForProject
    @MetricTypeID int,
    @ProjectID int,
    @Direction nvarchar(10)
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @NormalisedDirection nvarchar(10) = CASE WHEN UPPER(@Direction) = N'UP' THEN N'Up' ELSE N'Down' END;

    ;WITH CandidateMetrics AS
    (
        SELECT mt.MetricTypeID, mt.ProjectID, mt.MetricName,
            COALESCE(ptms.SortOrder, mt.SortOrder) AS SortOrder,
            CAST(CASE WHEN mt.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 1 ELSE 0 END AS bit) AS IsEnabledForProject,
            CAST(CASE WHEN mt.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 0 ELSE 1 END AS int) AS GroupRank
        FROM dbo.SceneMetricTypes mt
        LEFT JOIN dbo.ProjectTimelineMetricSettings ptms ON ptms.ProjectID = @ProjectID AND ptms.MetricTypeID = mt.MetricTypeID
        WHERE
            mt.ProjectID = @ProjectID
            OR ptms.ProjectID = @ProjectID
            OR
            (
                mt.ProjectID IS NULL
                AND mt.MetricName IN
                (
                    N'Overall Intensity', N'Tension', N'Emotional Weight', N'Action', N'Darkness',
                    N'Romance', N'Sexual Charge', N'Violence', N'Hope / Lightness', N'Comedy', N'Mystery'
                )
            )
    )
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY GroupRank ORDER BY SortOrder, MetricName, MetricTypeID) AS RowNumber,
        ROW_NUMBER() OVER (PARTITION BY GroupRank ORDER BY SortOrder, MetricName, MetricTypeID) * 10 AS NormalisedSortOrder
    INTO #OrderedMetrics
    FROM CandidateMetrics;

    UPDATE ptms
    SET SortOrder = ordered.NormalisedSortOrder
    FROM dbo.ProjectTimelineMetricSettings ptms
    INNER JOIN #OrderedMetrics ordered ON ordered.MetricTypeID = ptms.MetricTypeID
    WHERE ptms.ProjectID = @ProjectID
        AND ordered.IsEnabledForProject = 1;

    UPDATE mt
    SET SortOrder = ordered.NormalisedSortOrder
    FROM dbo.SceneMetricTypes mt
    INNER JOIN #OrderedMetrics ordered ON ordered.MetricTypeID = mt.MetricTypeID
    WHERE mt.ProjectID = @ProjectID
        AND ordered.IsEnabledForProject = 0;

    ;WITH OrderedMetrics AS
    (
        SELECT MetricTypeID, ProjectID, MetricName, NormalisedSortOrder AS SortOrder, IsEnabledForProject, GroupRank, RowNumber
        FROM #OrderedMetrics
    ),
    MovePair AS
    (
        SELECT currentMetric.MetricTypeID AS CurrentMetricTypeID,
            currentMetric.ProjectID AS CurrentProjectID,
            currentMetric.IsEnabledForProject AS CurrentIsEnabledForProject,
            currentMetric.SortOrder AS CurrentSortOrder,
            adjacentMetric.MetricTypeID AS AdjacentMetricTypeID,
            adjacentMetric.ProjectID AS AdjacentProjectID,
            adjacentMetric.IsEnabledForProject AS AdjacentIsEnabledForProject,
            adjacentMetric.SortOrder AS AdjacentSortOrder
        FROM OrderedMetrics currentMetric
        INNER JOIN OrderedMetrics adjacentMetric ON adjacentMetric.GroupRank = currentMetric.GroupRank
            AND adjacentMetric.RowNumber = CASE WHEN @NormalisedDirection = N'Up' THEN currentMetric.RowNumber - 1 ELSE currentMetric.RowNumber + 1 END
        WHERE currentMetric.MetricTypeID = @MetricTypeID
    )
    SELECT *
    INTO #MovePair
    FROM MovePair;

    IF NOT EXISTS (SELECT 1 FROM #MovePair)
    BEGIN
        SELECT CAST(0 AS bit);
        RETURN;
    END;

    IF EXISTS (SELECT 1 FROM #MovePair WHERE CurrentIsEnabledForProject = 0 AND CurrentProjectID IS NULL)
    BEGIN
        SELECT CAST(0 AS bit);
        RETURN;
    END;

    IF EXISTS (SELECT 1 FROM #MovePair WHERE AdjacentIsEnabledForProject = 0 AND AdjacentProjectID IS NULL)
    BEGIN
        SELECT CAST(0 AS bit);
        RETURN;
    END;

    UPDATE ptms
    SET SortOrder = mp.AdjacentSortOrder
    FROM dbo.ProjectTimelineMetricSettings ptms
    INNER JOIN #MovePair mp ON mp.CurrentMetricTypeID = ptms.MetricTypeID
    WHERE ptms.ProjectID = @ProjectID
        AND mp.CurrentIsEnabledForProject = 1;

    UPDATE mt
    SET SortOrder = mp.AdjacentSortOrder
    FROM dbo.SceneMetricTypes mt
    INNER JOIN #MovePair mp ON mp.CurrentMetricTypeID = mt.MetricTypeID
    WHERE mt.ProjectID = @ProjectID
        AND mp.CurrentIsEnabledForProject = 0;

    UPDATE ptms
    SET SortOrder = mp.CurrentSortOrder
    FROM dbo.ProjectTimelineMetricSettings ptms
    INNER JOIN #MovePair mp ON mp.AdjacentMetricTypeID = ptms.MetricTypeID
    WHERE ptms.ProjectID = @ProjectID
        AND mp.AdjacentIsEnabledForProject = 1;

    UPDATE mt
    SET SortOrder = mp.CurrentSortOrder
    FROM dbo.SceneMetricTypes mt
    INNER JOIN #MovePair mp ON mp.AdjacentMetricTypeID = mt.MetricTypeID
    WHERE mt.ProjectID = @ProjectID
        AND mp.AdjacentIsEnabledForProject = 0;

    SELECT CAST(1 AS bit);
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneMetricType_RemoveUnusedForProject
    @MetricTypeID int,
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;

    IF EXISTS
    (
        SELECT 1
        FROM dbo.SceneMetricTypes mt
        WHERE mt.MetricTypeID = @MetricTypeID
            AND mt.ProjectID = @ProjectID
            AND mt.IsActive = 0
            AND NOT EXISTS (SELECT 1 FROM dbo.SceneMetricValues smv WHERE smv.MetricTypeID = mt.MetricTypeID)
    )
    BEGIN
        DELETE FROM dbo.ProjectTimelineMetricSettings
        WHERE ProjectID = @ProjectID AND MetricTypeID = @MetricTypeID;

        DELETE FROM dbo.SceneMetricTypes
        WHERE MetricTypeID = @MetricTypeID AND ProjectID = @ProjectID;

        SELECT CAST(1 AS bit);
        RETURN;
    END;

    SELECT CAST(0 AS bit);
END;
GO

CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_EnsureDefaults
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;

    IF NOT EXISTS (SELECT 1 FROM dbo.Projects WHERE ProjectID = @ProjectID AND IsArchived = 0)
        RETURN;

    IF NOT EXISTS (SELECT 1 FROM dbo.ProjectTimelineSettings WHERE ProjectID = @ProjectID)
    BEGIN
        INSERT dbo.ProjectTimelineSettings
            (ProjectID, ShowSceneCards, ShowMetricShape, ShowPlotLines, ShowStoryAssets, ShowCharacterAppearances, ShowWarnings)
        VALUES
            (@ProjectID, 1, 1, 1, 1, 1, 1);
    END;
END;
GO

CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_MetricTypes
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT mt.MetricTypeID, mt.ProjectID, mt.MetricName, mt.Description, mt.MinValue, mt.MaxValue, mt.DefaultValue,
        ptms.SortOrder, mt.IsActive
    FROM dbo.ProjectTimelineMetricSettings ptms
    INNER JOIN dbo.SceneMetricTypes mt ON mt.MetricTypeID = ptms.MetricTypeID
    WHERE ptms.ProjectID = @ProjectID
        AND mt.IsActive = 1
        AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
    ORDER BY ptms.SortOrder, mt.SortOrder, mt.MetricName;
END;
GO
