SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

IF OBJECT_ID(N'dbo.ProjectTimelineSettings', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.ProjectTimelineSettings
    (
        ProjectTimelineSettingsID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_ProjectTimelineSettings PRIMARY KEY,
        ProjectID int NOT NULL,
        ShowSceneCards bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowSceneCards DEFAULT 1,
        ShowMetricShape bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowMetricShape DEFAULT 1,
        ShowPlotLines bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowPlotLines DEFAULT 1,
        ShowStoryAssets bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowStoryAssets DEFAULT 1,
        ShowCharacterAppearances bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowCharacterAppearances DEFAULT 1,
        ShowWarnings bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowWarnings DEFAULT 1,
        CreatedDate datetime2(0) NOT NULL CONSTRAINT DF_ProjectTimelineSettings_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2(0) NOT NULL CONSTRAINT DF_ProjectTimelineSettings_UpdatedDate DEFAULT SYSUTCDATETIME(),
        CONSTRAINT UQ_ProjectTimelineSettings_ProjectID UNIQUE(ProjectID),
        CONSTRAINT FK_ProjectTimelineSettings_Projects FOREIGN KEY(ProjectID) REFERENCES dbo.Projects(ProjectID)
    );
END;
GO

IF OBJECT_ID(N'dbo.ProjectTimelineMetricSettings', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.ProjectTimelineMetricSettings
    (
        ProjectID int NOT NULL,
        MetricTypeID int NOT NULL,
        SortOrder int NOT NULL,
        CreatedDate datetime2(0) NOT NULL CONSTRAINT DF_ProjectTimelineMetricSettings_CreatedDate DEFAULT SYSUTCDATETIME(),
        CONSTRAINT PK_ProjectTimelineMetricSettings PRIMARY KEY(ProjectID, MetricTypeID),
        CONSTRAINT FK_ProjectTimelineMetricSettings_Projects FOREIGN KEY(ProjectID) REFERENCES dbo.Projects(ProjectID),
        CONSTRAINT FK_ProjectTimelineMetricSettings_SceneMetricTypes FOREIGN KEY(MetricTypeID) REFERENCES dbo.SceneMetricTypes(MetricTypeID)
    );
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;

    IF NOT EXISTS (SELECT 1 FROM dbo.ProjectTimelineMetricSettings WHERE ProjectID = @ProjectID)
    BEGIN
        INSERT dbo.ProjectTimelineMetricSettings (ProjectID, MetricTypeID, SortOrder)
        SELECT @ProjectID, mt.MetricTypeID, mt.SortOrder
        FROM dbo.SceneMetricTypes mt
        WHERE mt.IsActive = 1
            AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
            AND mt.MetricName IN (N'Overall Intensity', N'Tension', N'Emotional Weight', N'Action');
    END;
END;
GO

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

    EXEC dbo.ProjectTimelineSettings_EnsureDefaults @ProjectID = @ProjectID;

    SELECT ProjectTimelineSettingsID, ProjectID, ShowSceneCards, ShowMetricShape, ShowPlotLines,
        ShowStoryAssets, ShowCharacterAppearances, ShowWarnings, CreatedDate, UpdatedDate
    FROM dbo.ProjectTimelineSettings
    WHERE ProjectID = @ProjectID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_MetricTypes
    @ProjectID int
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.ProjectTimelineMetricSettings_List
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;

    EXEC dbo.ProjectTimelineSettings_EnsureDefaults @ProjectID = @ProjectID;

    SELECT ptms.ProjectID, ptms.MetricTypeID, mt.MetricName, mt.SortOrder
    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

CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_Save
    @ProjectID int,
    @ShowSceneCards bit,
    @ShowMetricShape bit,
    @ShowPlotLines bit,
    @ShowStoryAssets bit,
    @ShowCharacterAppearances bit,
    @ShowWarnings bit,
    @MetricTypeIDs nvarchar(max) = NULL
AS
BEGIN
    SET NOCOUNT ON;

    EXEC dbo.ProjectTimelineSettings_EnsureDefaults @ProjectID = @ProjectID;

    UPDATE dbo.ProjectTimelineSettings
    SET ShowSceneCards = @ShowSceneCards,
        ShowMetricShape = @ShowMetricShape,
        ShowPlotLines = @ShowPlotLines,
        ShowStoryAssets = @ShowStoryAssets,
        ShowCharacterAppearances = @ShowCharacterAppearances,
        ShowWarnings = @ShowWarnings,
        UpdatedDate = SYSUTCDATETIME()
    WHERE ProjectID = @ProjectID;

    DELETE FROM dbo.ProjectTimelineMetricSettings
    WHERE ProjectID = @ProjectID;

    IF @MetricTypeIDs IS NOT NULL AND LTRIM(RTRIM(@MetricTypeIDs)) <> N''
    BEGIN
        INSERT dbo.ProjectTimelineMetricSettings (ProjectID, MetricTypeID, SortOrder)
        SELECT @ProjectID, mt.MetricTypeID, mt.SortOrder
        FROM dbo.SceneMetricTypes mt
        INNER JOIN
        (
            SELECT DISTINCT TRY_CONVERT(int, value) AS MetricTypeID
            FROM string_split(@MetricTypeIDs, N',')
            WHERE TRY_CONVERT(int, value) IS NOT NULL
        ) selected ON selected.MetricTypeID = mt.MetricTypeID
        WHERE mt.IsActive = 1 AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID);
    END;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Timeline_GetByProject
    @ProjectID int,
    @BookID int = NULL,
    @IncludeMetrics bit = 1,
    @SelectedMetricTypeIDs nvarchar(max) = NULL,
    @IncludePlotLines bit = 1
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @MetricSelection TABLE (MetricTypeID int NOT NULL PRIMARY KEY);
    INSERT @MetricSelection (MetricTypeID)
    SELECT DISTINCT TRY_CONVERT(int, value)
    FROM string_split(COALESCE(@SelectedMetricTypeIDs, N''), N',')
    WHERE TRY_CONVERT(int, value) IS NOT NULL;

    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 c.IsArchived = 0 AND b.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID)
    ORDER BY b.SortOrder, c.SortOrder;

    SELECT s.SceneID, s.ChapterID, s.SceneNumber, s.SceneTitle, s.Summary, s.POVCharacterID, s.PrimaryLocationID,
        location.LocationName AS PrimaryLocationName, location.LocationPath AS PrimaryLocationPath,
        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
    INNER JOIN dbo.TimeConfidences tc ON tc.TimeConfidenceID = s.TimeConfidenceID
    INNER JOIN dbo.RevisionStatuses rs ON rs.RevisionStatusID = s.RevisionStatusID
    LEFT JOIN dbo.DurationUnits du ON du.DurationUnitID = s.DurationUnitID
    LEFT JOIN dbo.LocationPaths location ON location.LocationID = s.PrimaryLocationID
    WHERE b.ProjectID = @ProjectID AND s.IsArchived = 0 AND c.IsArchived = 0 AND b.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID)
    ORDER BY b.SortOrder, c.SortOrder, s.SortOrder;

    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 (@BookID IS NULL OR b.BookID = @BookID)
    ORDER BY spt.SortOrder;

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

    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
    INNER JOIN dbo.SceneMetricTypes mt ON mt.IsActive = 1 AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
    LEFT JOIN dbo.SceneMetricValues smv ON smv.SceneID = s.SceneID AND smv.MetricTypeID = mt.MetricTypeID
    WHERE @IncludeMetrics = 1
        AND b.ProjectID = @ProjectID
        AND s.IsArchived = 0
        AND c.IsArchived = 0
        AND b.IsArchived = 0
        AND (@BookID IS NULL OR b.BookID = @BookID)
        AND (NOT EXISTS (SELECT 1 FROM @MetricSelection) OR mt.MetricTypeID IN (SELECT MetricTypeID FROM @MetricSelection))
    ORDER BY b.SortOrder, c.SortOrder, s.SortOrder, mt.SortOrder;

    SELECT pl.PlotLineID, pl.ProjectID, pl.BookID, b.BookTitle, pl.PlotLineName, pl.PlotLineTypeID, plt.TypeName AS PlotLineTypeName,
        pl.Description, pl.ParentPlotLineID, parent.PlotLineName AS ParentPlotLineName, pl.SortOrder, pl.Colour, pl.IsMainPlot, pl.IsVisibleOnTimeline,
        pl.CreatedDate, pl.UpdatedDate, pl.IsArchived
    FROM dbo.PlotLines pl
    INNER JOIN dbo.PlotLineTypes plt ON plt.PlotLineTypeID = pl.PlotLineTypeID
    LEFT JOIN dbo.Books b ON b.BookID = pl.BookID
    LEFT JOIN dbo.PlotLines parent ON parent.PlotLineID = pl.ParentPlotLineID
    WHERE @IncludePlotLines = 1
        AND pl.ProjectID = @ProjectID
        AND pl.IsArchived = 0
        AND pl.IsVisibleOnTimeline = 1
        AND (@BookID IS NULL OR pl.BookID IS NULL OR pl.BookID = @BookID)
    ORDER BY pl.SortOrder, pl.PlotLineName;

    SELECT te.ThreadEventID, te.PlotThreadID, pt.ThreadTitle, pt.PlotLineID, pl.PlotLineName, pl.Colour, te.SceneID, te.EventTypeID,
        tet.TypeName AS EventTypeName, tet.MarkerText, te.EventTitle, te.EventDescription, te.CreatedDate, te.UpdatedDate
    FROM dbo.ThreadEvents te
    INNER JOIN dbo.PlotThreads pt ON pt.PlotThreadID = te.PlotThreadID
    INNER JOIN dbo.PlotLines pl ON pl.PlotLineID = pt.PlotLineID
    INNER JOIN dbo.ThreadEventTypes tet ON tet.ThreadEventTypeID = te.EventTypeID
    INNER JOIN dbo.Scenes s ON s.SceneID = te.SceneID
    INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = c.BookID
    WHERE @IncludePlotLines = 1
        AND b.ProjectID = @ProjectID
        AND pl.IsArchived = 0
        AND pt.IsArchived = 0
        AND (@BookID IS NULL OR b.BookID = @BookID)
    ORDER BY pl.SortOrder, pt.ThreadTitle, b.SortOrder, c.SortOrder, s.SortOrder;
END;
GO
