SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

IF OBJECT_ID(N'dbo.SceneMetricTypes', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.SceneMetricTypes
    (
        MetricTypeID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_SceneMetricTypes PRIMARY KEY,
        ProjectID int NULL,
        MetricName nvarchar(100) NOT NULL,
        Description nvarchar(500) NULL,
        MinValue int NOT NULL CONSTRAINT DF_SceneMetricTypes_MinValue DEFAULT 1,
        MaxValue int NOT NULL CONSTRAINT DF_SceneMetricTypes_MaxValue DEFAULT 10,
        DefaultValue int NOT NULL CONSTRAINT DF_SceneMetricTypes_DefaultValue DEFAULT 5,
        SortOrder int NOT NULL,
        IsActive bit NOT NULL CONSTRAINT DF_SceneMetricTypes_IsActive DEFAULT 1,
        CONSTRAINT FK_SceneMetricTypes_Projects FOREIGN KEY (ProjectID) REFERENCES dbo.Projects(ProjectID),
        CONSTRAINT CK_SceneMetricTypes_Range CHECK (MinValue < MaxValue AND DefaultValue BETWEEN MinValue AND MaxValue)
    );
END;
GO

IF OBJECT_ID(N'dbo.SceneMetricValues', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.SceneMetricValues
    (
        SceneID int NOT NULL,
        MetricTypeID int NOT NULL,
        Value int NOT NULL,
        Notes nvarchar(500) NULL,
        CONSTRAINT PK_SceneMetricValues PRIMARY KEY (SceneID, MetricTypeID),
        CONSTRAINT FK_SceneMetricValues_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID),
        CONSTRAINT FK_SceneMetricValues_SceneMetricTypes FOREIGN KEY (MetricTypeID) REFERENCES dbo.SceneMetricTypes(MetricTypeID),
        CONSTRAINT CK_SceneMetricValues_Value CHECK (Value BETWEEN 1 AND 10)
    );
END;
GO

IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_SceneMetricTypes_ProjectID_SortOrder' AND object_id = OBJECT_ID(N'dbo.SceneMetricTypes'))
    CREATE INDEX IX_SceneMetricTypes_ProjectID_SortOrder ON dbo.SceneMetricTypes(ProjectID, IsActive, SortOrder);
GO

MERGE dbo.SceneMetricTypes AS target
USING (VALUES
    (N'Overall Intensity', N'General dramatic intensity for the scene.', 1, 10, 5, 10),
    (N'Tension', N'Pressure, suspense, uncertainty, or conflict.', 1, 10, 5, 20),
    (N'Emotional Weight', N'Emotional load carried by the scene.', 1, 10, 5, 30),
    (N'Action', N'Physical action, movement, or event energy.', 1, 10, 3, 40),
    (N'Darkness', N'Darkness, bleakness, fear, or threat.', 1, 10, 3, 50),
    (N'Romance', N'Romantic focus or intimacy.', 1, 10, 1, 60),
    (N'Sexual Charge', N'Sexual tension or sensual charge.', 1, 10, 1, 70),
    (N'Violence', N'Violent action, injury, or threat.', 1, 10, 1, 80),
    (N'Hope / Lightness', N'Hope, relief, warmth, or tonal lightness.', 1, 10, 4, 90),
    (N'Comedy', N'Humour or comic relief.', 1, 10, 1, 100),
    (N'Mystery', N'Questions, clue energy, and mystery pressure.', 1, 10, 5, 110)
) AS source (MetricName, Description, MinValue, MaxValue, DefaultValue, SortOrder)
ON target.ProjectID IS NULL AND target.MetricName = source.MetricName
WHEN NOT MATCHED THEN
    INSERT (ProjectID, MetricName, Description, MinValue, MaxValue, DefaultValue, SortOrder, IsActive)
    VALUES (NULL, source.MetricName, source.Description, source.MinValue, source.MaxValue, source.DefaultValue, source.SortOrder, 1);
GO

CREATE OR ALTER PROCEDURE dbo.SceneMetricType_List
    @ProjectID int = NULL
AS
BEGIN
    SET NOCOUNT ON;

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

CREATE OR ALTER PROCEDURE dbo.SceneMetric_EnsureDefaults
    @SceneID int
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @ProjectID int;

    SELECT @ProjectID = b.ProjectID
    FROM dbo.Scenes s
    INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = c.BookID
    WHERE s.SceneID = @SceneID;

    INSERT dbo.SceneMetricValues (SceneID, MetricTypeID, Value, Notes)
    SELECT @SceneID, mt.MetricTypeID, mt.DefaultValue, NULL
    FROM dbo.SceneMetricTypes mt
    WHERE mt.IsActive = 1
        AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
        AND NOT EXISTS
        (
            SELECT 1
            FROM dbo.SceneMetricValues smv
            WHERE smv.SceneID = @SceneID AND smv.MetricTypeID = mt.MetricTypeID
        );
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneMetric_ListByScene
    @SceneID int
AS
BEGIN
    SET NOCOUNT ON;

    EXEC dbo.SceneMetric_EnsureDefaults @SceneID = @SceneID;

    SELECT mt.MetricTypeID, mt.ProjectID, mt.MetricName, mt.Description, mt.MinValue, mt.MaxValue,
        mt.DefaultValue, mt.SortOrder, mt.IsActive, smv.SceneID, smv.Value, smv.Notes
    FROM dbo.SceneMetricTypes mt
    INNER JOIN dbo.SceneMetricValues smv ON smv.MetricTypeID = mt.MetricTypeID AND smv.SceneID = @SceneID
    WHERE mt.IsActive = 1
    ORDER BY mt.SortOrder, mt.MetricName;
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneMetric_SaveValue
    @SceneID int,
    @MetricTypeID int,
    @Value int,
    @Notes nvarchar(500) = NULL
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @MinValue int;
    DECLARE @MaxValue int;

    SELECT @MinValue = MinValue, @MaxValue = MaxValue
    FROM dbo.SceneMetricTypes
    WHERE MetricTypeID = @MetricTypeID AND IsActive = 1;

    IF @MinValue IS NULL
        THROW 50001, 'Metric type does not exist.', 1;

    IF @Value < @MinValue OR @Value > @MaxValue
        THROW 50002, 'Metric value is outside the configured range.', 1;

    MERGE dbo.SceneMetricValues AS target
    USING (SELECT @SceneID AS SceneID, @MetricTypeID AS MetricTypeID) AS source
    ON target.SceneID = source.SceneID AND target.MetricTypeID = source.MetricTypeID
    WHEN MATCHED THEN
        UPDATE SET Value = @Value, Notes = @Notes
    WHEN NOT MATCHED THEN
        INSERT (SceneID, MetricTypeID, Value, Notes)
        VALUES (@SceneID, @MetricTypeID, @Value, @Notes);
END;
GO

CREATE OR ALTER PROCEDURE dbo.Scene_Get
    @SceneID int
AS
BEGIN
    SET NOCOUNT ON;

    EXEC dbo.SceneMetric_EnsureDefaults @SceneID = @SceneID;

    SELECT s.SceneID, s.ChapterID, s.SceneNumber, s.SceneTitle, s.Summary, s.POVCharacterID,
        s.PrimaryLocationID, s.SortOrder, s.TimeModeID, tm.TimeModeName, s.StartDateTime,
        s.EndDateTime, s.DurationAmount, s.DurationUnitID, du.DurationUnitName, s.RelativeTimeText,
        s.TimeConfidenceID, tc.TimeConfidenceName, s.ScenePurposeNotes, s.SceneOutcomeNotes,
        s.RevisionStatusID, rs.StatusName AS RevisionStatusName, s.CreatedDate, s.UpdatedDate, s.IsArchived
    FROM dbo.Scenes s
    INNER JOIN dbo.TimeModes tm ON tm.TimeModeID = s.TimeModeID
    LEFT JOIN dbo.DurationUnits du ON du.DurationUnitID = s.DurationUnitID
    INNER JOIN dbo.TimeConfidences tc ON tc.TimeConfidenceID = s.TimeConfidenceID
    INNER JOIN dbo.RevisionStatuses rs ON rs.RevisionStatusID = s.RevisionStatusID
    WHERE s.SceneID = @SceneID AND s.IsArchived = 0;

    SELECT sp.ScenePurposeTypeID
    FROM dbo.ScenePurposes sp
    WHERE sp.SceneID = @SceneID;

    SELECT mt.MetricTypeID, mt.ProjectID, mt.MetricName, mt.Description, mt.MinValue, mt.MaxValue,
        mt.DefaultValue, mt.SortOrder, mt.IsActive, smv.SceneID, smv.Value, smv.Notes
    FROM dbo.SceneMetricTypes mt
    INNER JOIN dbo.SceneMetricValues smv ON smv.MetricTypeID = mt.MetricTypeID AND smv.SceneID = @SceneID
    WHERE mt.IsActive = 1
    ORDER BY mt.SortOrder, mt.MetricName;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Timeline_GetByProject
    @ProjectID int,
    @BookID int = NULL
AS
BEGIN
    SET NOCOUNT ON;

    SELECT ProjectID, ProjectName, Description, CreatedDate, UpdatedDate, IsArchived
    FROM dbo.Projects
    WHERE ProjectID = @ProjectID AND IsArchived = 0;

    SELECT BookID, ProjectID, BookTitle, BookNumber, Description, SortOrder, CreatedDate, UpdatedDate, IsArchived
    FROM dbo.Books
    WHERE ProjectID = @ProjectID AND IsArchived = 0 AND (@BookID IS NULL OR BookID = @BookID)
    ORDER BY SortOrder, BookNumber;

    SELECT c.ChapterID, c.BookID, c.ChapterNumber, c.ChapterTitle, c.POVCharacterID, c.Summary,
        c.SortOrder, c.RevisionStatusID, rs.StatusName AS RevisionStatusName,
        c.CreatedDate, c.UpdatedDate, c.IsArchived
    FROM dbo.Chapters c
    INNER JOIN dbo.Books b ON b.BookID = c.BookID
    INNER JOIN dbo.RevisionStatuses rs ON rs.RevisionStatusID = c.RevisionStatusID
    WHERE b.ProjectID = @ProjectID AND b.IsArchived = 0 AND c.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID)
    ORDER BY b.SortOrder, c.SortOrder, c.ChapterNumber;

    SELECT s.SceneID, s.ChapterID, s.SceneNumber, s.SceneTitle, s.Summary, s.POVCharacterID,
        s.PrimaryLocationID, s.SortOrder, s.TimeModeID, tm.TimeModeName, s.StartDateTime,
        s.EndDateTime, s.DurationAmount, s.DurationUnitID, du.DurationUnitName, s.RelativeTimeText,
        s.TimeConfidenceID, tc.TimeConfidenceName, s.ScenePurposeNotes, s.SceneOutcomeNotes,
        s.RevisionStatusID, rs.StatusName AS RevisionStatusName, s.CreatedDate, s.UpdatedDate, s.IsArchived
    FROM dbo.Scenes s
    INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = c.BookID
    INNER JOIN dbo.TimeModes tm ON tm.TimeModeID = s.TimeModeID
    LEFT JOIN dbo.DurationUnits du ON du.DurationUnitID = s.DurationUnitID
    INNER JOIN dbo.TimeConfidences tc ON tc.TimeConfidenceID = s.TimeConfidenceID
    INNER JOIN dbo.RevisionStatuses rs ON rs.RevisionStatusID = s.RevisionStatusID
    WHERE b.ProjectID = @ProjectID AND b.IsArchived = 0 AND c.IsArchived = 0 AND s.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID)
    ORDER BY b.SortOrder, c.SortOrder, s.SortOrder, s.SceneNumber;

    SELECT sp.SceneID, spt.ScenePurposeTypeID, spt.PurposeName, spt.SortOrder
    FROM dbo.ScenePurposes sp
    INNER JOIN dbo.ScenePurposeTypes spt ON spt.ScenePurposeTypeID = sp.ScenePurposeTypeID
    INNER JOIN dbo.Scenes s ON s.SceneID = sp.SceneID
    INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = c.BookID
    WHERE b.ProjectID = @ProjectID AND b.IsArchived = 0 AND c.IsArchived = 0 AND s.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID)
    ORDER BY sp.SceneID, spt.SortOrder;

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

    SELECT s.SceneID, mt.MetricTypeID, mt.MetricName, COALESCE(smv.Value, mt.DefaultValue) AS Value, smv.Notes
    FROM dbo.Scenes s
    INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = c.BookID
    CROSS JOIN dbo.SceneMetricTypes mt
    LEFT JOIN dbo.SceneMetricValues smv ON smv.SceneID = s.SceneID AND smv.MetricTypeID = mt.MetricTypeID
    WHERE b.ProjectID = @ProjectID
        AND b.IsArchived = 0
        AND c.IsArchived = 0
        AND s.IsArchived = 0
        AND mt.IsActive = 1
        AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
        AND (@BookID IS NULL OR b.BookID = @BookID)
    ORDER BY b.SortOrder, c.SortOrder, s.SortOrder, mt.SortOrder;
END;
GO
