SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

IF OBJECT_ID(N'dbo.ScenePurposes', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.ScenePurposes
    (
        SceneID int NOT NULL,
        ScenePurposeTypeID int NOT NULL,
        CONSTRAINT PK_ScenePurposes PRIMARY KEY (SceneID, ScenePurposeTypeID)
    );
END;
GO

IF OBJECT_ID(N'dbo.SceneOutcomes', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.SceneOutcomes
    (
        SceneOutcomeID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_SceneOutcomes PRIMARY KEY,
        SceneID int NOT NULL,
        OutcomeDescription nvarchar(1000) NOT NULL,
        OutcomeTypeID int NULL,
        CreatedDate datetime2 NOT NULL CONSTRAINT DF_SceneOutcomes_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2 NOT NULL CONSTRAINT DF_SceneOutcomes_UpdatedDate DEFAULT SYSUTCDATETIME()
    );
END;
GO

IF OBJECT_ID(N'dbo.ScenePurposeTypes', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.ScenePurposeTypes
    (
        ScenePurposeTypeID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_ScenePurposeTypes PRIMARY KEY,
        PurposeName nvarchar(100) NOT NULL,
        SortOrder int NOT NULL,
        IsArchived bit NOT NULL CONSTRAINT DF_ScenePurposeTypes_IsArchived DEFAULT 0,
        CONSTRAINT UQ_ScenePurposeTypes_PurposeName UNIQUE (PurposeName)
    );
END;
GO

IF OBJECT_ID(N'dbo.TimeConfidences', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.TimeConfidences
    (
        TimeConfidenceID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_TimeConfidences PRIMARY KEY,
        TimeConfidenceName nvarchar(100) NOT NULL,
        SortOrder int NOT NULL,
        CONSTRAINT UQ_TimeConfidences_TimeConfidenceName UNIQUE (TimeConfidenceName)
    );
END;
GO

IF OBJECT_ID(N'dbo.DurationUnits', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.DurationUnits
    (
        DurationUnitID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_DurationUnits PRIMARY KEY,
        DurationUnitName nvarchar(100) NOT NULL,
        SortOrder int NOT NULL,
        CONSTRAINT UQ_DurationUnits_DurationUnitName UNIQUE (DurationUnitName)
    );
END;
GO

IF OBJECT_ID(N'dbo.TimeModes', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.TimeModes
    (
        TimeModeID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_TimeModes PRIMARY KEY,
        TimeModeName nvarchar(100) NOT NULL,
        SortOrder int NOT NULL,
        CONSTRAINT UQ_TimeModes_TimeModeName UNIQUE (TimeModeName)
    );
END;
GO

IF OBJECT_ID(N'dbo.RevisionStatuses', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.RevisionStatuses
    (
        RevisionStatusID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_RevisionStatuses PRIMARY KEY,
        StatusName nvarchar(100) NOT NULL,
        SortOrder int NOT NULL,
        CONSTRAINT UQ_RevisionStatuses_StatusName UNIQUE (StatusName)
    );
END;
GO

IF OBJECT_ID(N'dbo.Projects', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.Projects
    (
        ProjectID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_Projects PRIMARY KEY,
        ProjectName nvarchar(200) NOT NULL,
        Description nvarchar(max) NULL,
        CreatedDate datetime2 NOT NULL CONSTRAINT DF_Projects_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2 NOT NULL CONSTRAINT DF_Projects_UpdatedDate DEFAULT SYSUTCDATETIME(),
        IsArchived bit NOT NULL CONSTRAINT DF_Projects_IsArchived DEFAULT 0
    );
END;
GO

IF OBJECT_ID(N'dbo.Books', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.Books
    (
        BookID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_Books PRIMARY KEY,
        ProjectID int NOT NULL,
        BookTitle nvarchar(200) NOT NULL,
        BookNumber int NOT NULL,
        Description nvarchar(max) NULL,
        SortOrder int NOT NULL,
        CreatedDate datetime2 NOT NULL CONSTRAINT DF_Books_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2 NOT NULL CONSTRAINT DF_Books_UpdatedDate DEFAULT SYSUTCDATETIME(),
        IsArchived bit NOT NULL CONSTRAINT DF_Books_IsArchived DEFAULT 0,
        CONSTRAINT FK_Books_Projects FOREIGN KEY (ProjectID) REFERENCES dbo.Projects(ProjectID)
    );
END;
GO

IF OBJECT_ID(N'dbo.Chapters', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.Chapters
    (
        ChapterID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_Chapters PRIMARY KEY,
        BookID int NOT NULL,
        ChapterNumber decimal(9,2) NOT NULL,
        ChapterTitle nvarchar(200) NOT NULL,
        POVCharacterID int NULL,
        Summary nvarchar(max) NULL,
        SortOrder int NOT NULL,
        RevisionStatusID int NOT NULL,
        CreatedDate datetime2 NOT NULL CONSTRAINT DF_Chapters_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2 NOT NULL CONSTRAINT DF_Chapters_UpdatedDate DEFAULT SYSUTCDATETIME(),
        IsArchived bit NOT NULL CONSTRAINT DF_Chapters_IsArchived DEFAULT 0,
        CONSTRAINT FK_Chapters_Books FOREIGN KEY (BookID) REFERENCES dbo.Books(BookID),
        CONSTRAINT FK_Chapters_RevisionStatuses FOREIGN KEY (RevisionStatusID) REFERENCES dbo.RevisionStatuses(RevisionStatusID)
    );
END;
GO

IF OBJECT_ID(N'dbo.Scenes', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.Scenes
    (
        SceneID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_Scenes PRIMARY KEY,
        ChapterID int NOT NULL,
        SceneNumber decimal(9,2) NOT NULL,
        SceneTitle nvarchar(200) NOT NULL,
        Summary nvarchar(max) NULL,
        POVCharacterID int NULL,
        PrimaryLocationID int NULL,
        SortOrder int NOT NULL,
        TimeModeID int NOT NULL,
        StartDateTime datetime2 NULL,
        EndDateTime datetime2 NULL,
        DurationAmount decimal(9,2) NULL,
        DurationUnitID int NULL,
        RelativeTimeText nvarchar(200) NULL,
        TimeConfidenceID int NOT NULL,
        ScenePurposeNotes nvarchar(max) NULL,
        SceneOutcomeNotes nvarchar(max) NULL,
        RevisionStatusID int NOT NULL,
        CreatedDate datetime2 NOT NULL CONSTRAINT DF_Scenes_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2 NOT NULL CONSTRAINT DF_Scenes_UpdatedDate DEFAULT SYSUTCDATETIME(),
        IsArchived bit NOT NULL CONSTRAINT DF_Scenes_IsArchived DEFAULT 0,
        CONSTRAINT FK_Scenes_Chapters FOREIGN KEY (ChapterID) REFERENCES dbo.Chapters(ChapterID),
        CONSTRAINT FK_Scenes_TimeModes FOREIGN KEY (TimeModeID) REFERENCES dbo.TimeModes(TimeModeID),
        CONSTRAINT FK_Scenes_DurationUnits FOREIGN KEY (DurationUnitID) REFERENCES dbo.DurationUnits(DurationUnitID),
        CONSTRAINT FK_Scenes_TimeConfidences FOREIGN KEY (TimeConfidenceID) REFERENCES dbo.TimeConfidences(TimeConfidenceID),
        CONSTRAINT FK_Scenes_RevisionStatuses FOREIGN KEY (RevisionStatusID) REFERENCES dbo.RevisionStatuses(RevisionStatusID)
    );
END;
GO

IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = N'FK_ScenePurposes_Scenes')
    ALTER TABLE dbo.ScenePurposes ADD CONSTRAINT FK_ScenePurposes_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID);
GO
IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = N'FK_ScenePurposes_ScenePurposeTypes')
    ALTER TABLE dbo.ScenePurposes ADD CONSTRAINT FK_ScenePurposes_ScenePurposeTypes FOREIGN KEY (ScenePurposeTypeID) REFERENCES dbo.ScenePurposeTypes(ScenePurposeTypeID);
GO
IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = N'FK_SceneOutcomes_Scenes')
    ALTER TABLE dbo.SceneOutcomes ADD CONSTRAINT FK_SceneOutcomes_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID);
GO

IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Books_ProjectID_SortOrder' AND object_id = OBJECT_ID(N'dbo.Books'))
    CREATE INDEX IX_Books_ProjectID_SortOrder ON dbo.Books(ProjectID, IsArchived, SortOrder);
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Chapters_BookID_SortOrder' AND object_id = OBJECT_ID(N'dbo.Chapters'))
    CREATE INDEX IX_Chapters_BookID_SortOrder ON dbo.Chapters(BookID, IsArchived, SortOrder);
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Scenes_ChapterID_SortOrder' AND object_id = OBJECT_ID(N'dbo.Scenes'))
    CREATE INDEX IX_Scenes_ChapterID_SortOrder ON dbo.Scenes(ChapterID, IsArchived, SortOrder);
GO

MERGE dbo.RevisionStatuses AS target
USING (VALUES
    (N'Planned', 10), (N'Outlined', 20), (N'Drafted', 30), (N'Needs Work', 40),
    (N'Revised', 50), (N'Polished', 60), (N'Locked', 70), (N'Cut Candidate', 80)
) AS source (StatusName, SortOrder)
ON target.StatusName = source.StatusName
WHEN NOT MATCHED THEN INSERT (StatusName, SortOrder) VALUES (source.StatusName, source.SortOrder);
GO

MERGE dbo.TimeModes AS target
USING (VALUES
    (N'Exact DateTime', 10), (N'Exact Date', 20), (N'Relative', 30), (N'Approximate', 40),
    (N'Unknown', 50), (N'Flashback', 60), (N'Timeless / Memory', 70)
) AS source (TimeModeName, SortOrder)
ON target.TimeModeName = source.TimeModeName
WHEN NOT MATCHED THEN INSERT (TimeModeName, SortOrder) VALUES (source.TimeModeName, source.SortOrder);
GO

MERGE dbo.DurationUnits AS target
USING (VALUES
    (N'Minutes', 10), (N'Hours', 20), (N'Days', 30), (N'Weeks', 40),
    (N'Months', 50), (N'Years', 60), (N'Unknown', 70)
) AS source (DurationUnitName, SortOrder)
ON target.DurationUnitName = source.DurationUnitName
WHEN NOT MATCHED THEN INSERT (DurationUnitName, SortOrder) VALUES (source.DurationUnitName, source.SortOrder);
GO

MERGE dbo.TimeConfidences AS target
USING (VALUES
    (N'Confirmed', 10), (N'Implied', 20), (N'Estimated', 30), (N'Unknown', 40)
) AS source (TimeConfidenceName, SortOrder)
ON target.TimeConfidenceName = source.TimeConfidenceName
WHEN NOT MATCHED THEN INSERT (TimeConfidenceName, SortOrder) VALUES (source.TimeConfidenceName, source.SortOrder);
GO

MERGE dbo.ScenePurposeTypes AS target
USING (VALUES
    (N'Advances Plot', 10), (N'Character Development', 20), (N'Relationship Development', 30),
    (N'Setup', 40), (N'Payoff', 50), (N'Reveal', 60), (N'Exposition', 70),
    (N'Mystery', 80), (N'Emotional Recovery', 90), (N'Comic Relief', 100),
    (N'Action', 110), (N'Transition / Travel', 120), (N'Location Change', 130),
    (N'Time Passage', 140), (N'Consequence', 150), (N'Reversal', 160)
) AS source (PurposeName, SortOrder)
ON target.PurposeName = source.PurposeName
WHEN NOT MATCHED THEN INSERT (PurposeName, SortOrder) VALUES (source.PurposeName, source.SortOrder);
GO

CREATE OR ALTER PROCEDURE dbo.Project_List
AS
BEGIN
    SET NOCOUNT ON;
    SELECT ProjectID, ProjectName, Description, CreatedDate, UpdatedDate, IsArchived
    FROM dbo.Projects
    WHERE IsArchived = 0
    ORDER BY ProjectName;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Project_Get
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT ProjectID, ProjectName, Description, CreatedDate, UpdatedDate, IsArchived
    FROM dbo.Projects
    WHERE ProjectID = @ProjectID AND IsArchived = 0;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Project_Save
    @ProjectID int = NULL,
    @ProjectName nvarchar(200),
    @Description nvarchar(max) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    IF @ProjectID IS NULL OR @ProjectID = 0
    BEGIN
        INSERT dbo.Projects (ProjectName, Description)
        VALUES (@ProjectName, @Description);
        SELECT CAST(SCOPE_IDENTITY() AS int) AS ProjectID;
        RETURN;
    END;

    UPDATE dbo.Projects
    SET ProjectName = @ProjectName,
        Description = @Description,
        UpdatedDate = SYSUTCDATETIME()
    WHERE ProjectID = @ProjectID;

    SELECT @ProjectID AS ProjectID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Project_Archive
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;
    UPDATE dbo.Projects SET IsArchived = 1, UpdatedDate = SYSUTCDATETIME() WHERE ProjectID = @ProjectID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Book_ListByProject
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT BookID, ProjectID, BookTitle, BookNumber, Description, SortOrder, CreatedDate, UpdatedDate, IsArchived
    FROM dbo.Books
    WHERE ProjectID = @ProjectID AND IsArchived = 0
    ORDER BY SortOrder, BookNumber, BookTitle;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Book_Get
    @BookID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT BookID, ProjectID, BookTitle, BookNumber, Description, SortOrder, CreatedDate, UpdatedDate, IsArchived
    FROM dbo.Books
    WHERE BookID = @BookID AND IsArchived = 0;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Book_Save
    @BookID int = NULL,
    @ProjectID int,
    @BookTitle nvarchar(200),
    @BookNumber int,
    @Description nvarchar(max) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    IF @BookID IS NULL OR @BookID = 0
    BEGIN
        DECLARE @NextBookOrder int = ISNULL((SELECT MAX(SortOrder) FROM dbo.Books WHERE ProjectID = @ProjectID), 0) + 10;
        INSERT dbo.Books (ProjectID, BookTitle, BookNumber, Description, SortOrder)
        VALUES (@ProjectID, @BookTitle, @BookNumber, @Description, @NextBookOrder);
        SELECT CAST(SCOPE_IDENTITY() AS int) AS BookID;
        RETURN;
    END;

    UPDATE dbo.Books
    SET BookTitle = @BookTitle,
        BookNumber = @BookNumber,
        Description = @Description,
        UpdatedDate = SYSUTCDATETIME()
    WHERE BookID = @BookID;

    SELECT @BookID AS BookID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Book_Archive
    @BookID int
AS
BEGIN
    SET NOCOUNT ON;
    UPDATE dbo.Books SET IsArchived = 1, UpdatedDate = SYSUTCDATETIME() WHERE BookID = @BookID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Chapter_ListByBook
    @BookID int
AS
BEGIN
    SET NOCOUNT ON;
    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.RevisionStatuses rs ON rs.RevisionStatusID = c.RevisionStatusID
    WHERE c.BookID = @BookID AND c.IsArchived = 0
    ORDER BY c.SortOrder, c.ChapterNumber, c.ChapterTitle;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Chapter_Get
    @ChapterID int
AS
BEGIN
    SET NOCOUNT ON;
    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.RevisionStatuses rs ON rs.RevisionStatusID = c.RevisionStatusID
    WHERE c.ChapterID = @ChapterID AND c.IsArchived = 0;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Chapter_Save
    @ChapterID int = NULL,
    @BookID int,
    @ChapterNumber decimal(9,2),
    @ChapterTitle nvarchar(200),
    @Summary nvarchar(max) = NULL,
    @RevisionStatusID int
AS
BEGIN
    SET NOCOUNT ON;
    IF @ChapterID IS NULL OR @ChapterID = 0
    BEGIN
        DECLARE @NextChapterOrder int = ISNULL((SELECT MAX(SortOrder) FROM dbo.Chapters WHERE BookID = @BookID), 0) + 10;
        INSERT dbo.Chapters (BookID, ChapterNumber, ChapterTitle, Summary, SortOrder, RevisionStatusID)
        VALUES (@BookID, @ChapterNumber, @ChapterTitle, @Summary, @NextChapterOrder, @RevisionStatusID);
        SELECT CAST(SCOPE_IDENTITY() AS int) AS ChapterID;
        RETURN;
    END;

    UPDATE dbo.Chapters
    SET ChapterNumber = @ChapterNumber,
        ChapterTitle = @ChapterTitle,
        Summary = @Summary,
        RevisionStatusID = @RevisionStatusID,
        UpdatedDate = SYSUTCDATETIME()
    WHERE ChapterID = @ChapterID;

    SELECT @ChapterID AS ChapterID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Chapter_Archive
    @ChapterID int
AS
BEGIN
    SET NOCOUNT ON;
    UPDATE dbo.Chapters SET IsArchived = 1, UpdatedDate = SYSUTCDATETIME() WHERE ChapterID = @ChapterID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Scene_ListByChapter
    @ChapterID int
AS
BEGIN
    SET NOCOUNT ON;
    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.ChapterID = @ChapterID AND s.IsArchived = 0
    ORDER BY s.SortOrder, s.SceneNumber, s.SceneTitle;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Scene_Get
    @SceneID int
AS
BEGIN
    SET NOCOUNT ON;
    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 ScenePurposeTypeID
    FROM dbo.ScenePurposes
    WHERE SceneID = @SceneID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Scene_Save
    @SceneID int = NULL,
    @ChapterID int,
    @SceneNumber decimal(9,2),
    @SceneTitle nvarchar(200),
    @Summary nvarchar(max) = NULL,
    @TimeModeID int,
    @StartDateTime datetime2 = NULL,
    @EndDateTime datetime2 = NULL,
    @DurationAmount decimal(9,2) = NULL,
    @DurationUnitID int = NULL,
    @RelativeTimeText nvarchar(200) = NULL,
    @TimeConfidenceID int,
    @ScenePurposeNotes nvarchar(max) = NULL,
    @SceneOutcomeNotes nvarchar(max) = NULL,
    @RevisionStatusID int
AS
BEGIN
    SET NOCOUNT ON;
    IF @SceneID IS NULL OR @SceneID = 0
    BEGIN
        DECLARE @NextSceneOrder int = ISNULL((SELECT MAX(SortOrder) FROM dbo.Scenes WHERE ChapterID = @ChapterID), 0) + 10;
        INSERT dbo.Scenes
        (
            ChapterID, SceneNumber, SceneTitle, Summary, SortOrder, TimeModeID, StartDateTime,
            EndDateTime, DurationAmount, DurationUnitID, RelativeTimeText, TimeConfidenceID,
            ScenePurposeNotes, SceneOutcomeNotes, RevisionStatusID
        )
        VALUES
        (
            @ChapterID, @SceneNumber, @SceneTitle, @Summary, @NextSceneOrder, @TimeModeID, @StartDateTime,
            @EndDateTime, @DurationAmount, @DurationUnitID, @RelativeTimeText, @TimeConfidenceID,
            @ScenePurposeNotes, @SceneOutcomeNotes, @RevisionStatusID
        );
        SELECT CAST(SCOPE_IDENTITY() AS int) AS SceneID;
        RETURN;
    END;

    UPDATE dbo.Scenes
    SET SceneNumber = @SceneNumber,
        SceneTitle = @SceneTitle,
        Summary = @Summary,
        TimeModeID = @TimeModeID,
        StartDateTime = @StartDateTime,
        EndDateTime = @EndDateTime,
        DurationAmount = @DurationAmount,
        DurationUnitID = @DurationUnitID,
        RelativeTimeText = @RelativeTimeText,
        TimeConfidenceID = @TimeConfidenceID,
        ScenePurposeNotes = @ScenePurposeNotes,
        SceneOutcomeNotes = @SceneOutcomeNotes,
        RevisionStatusID = @RevisionStatusID,
        UpdatedDate = SYSUTCDATETIME()
    WHERE SceneID = @SceneID;

    SELECT @SceneID AS SceneID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Scene_SavePurposes
    @SceneID int,
    @PurposeIds nvarchar(max)
AS
BEGIN
    SET NOCOUNT ON;
    DELETE FROM dbo.ScenePurposes WHERE SceneID = @SceneID;

    INSERT dbo.ScenePurposes (SceneID, ScenePurposeTypeID)
    SELECT @SceneID, TRY_CAST(value AS int)
    FROM STRING_SPLIT(ISNULL(@PurposeIds, N''), N',')
    WHERE TRY_CAST(value AS int) IS NOT NULL;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Scene_Archive
    @SceneID int
AS
BEGIN
    SET NOCOUNT ON;
    UPDATE dbo.Scenes SET IsArchived = 1, UpdatedDate = SYSUTCDATETIME() WHERE SceneID = @SceneID;
END;
GO

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

    DECLARE @ChapterID int;
    DECLARE @CurrentSortOrder int;
    DECLARE @SwapSceneID int;
    DECLARE @SwapSortOrder int;

    SELECT @ChapterID = ChapterID, @CurrentSortOrder = SortOrder
    FROM dbo.Scenes
    WHERE SceneID = @SceneID AND IsArchived = 0;

    IF @ChapterID IS NULL RETURN;

    IF @Direction = N'Up'
    BEGIN
        SELECT TOP (1) @SwapSceneID = SceneID, @SwapSortOrder = SortOrder
        FROM dbo.Scenes
        WHERE ChapterID = @ChapterID AND IsArchived = 0 AND SortOrder < @CurrentSortOrder
        ORDER BY SortOrder DESC;
    END
    ELSE
    BEGIN
        SELECT TOP (1) @SwapSceneID = SceneID, @SwapSortOrder = SortOrder
        FROM dbo.Scenes
        WHERE ChapterID = @ChapterID AND IsArchived = 0 AND SortOrder > @CurrentSortOrder
        ORDER BY SortOrder ASC;
    END;

    IF @SwapSceneID IS NULL RETURN;

    UPDATE dbo.Scenes SET SortOrder = @SwapSortOrder, UpdatedDate = SYSUTCDATETIME() WHERE SceneID = @SceneID;
    UPDATE dbo.Scenes SET SortOrder = @CurrentSortOrder, UpdatedDate = SYSUTCDATETIME() WHERE SceneID = @SwapSceneID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Lookup_All
AS
BEGIN
    SET NOCOUNT ON;
    SELECT RevisionStatusID, StatusName, SortOrder FROM dbo.RevisionStatuses ORDER BY SortOrder;
    SELECT TimeModeID, TimeModeName, SortOrder FROM dbo.TimeModes ORDER BY SortOrder;
    SELECT DurationUnitID, DurationUnitName, SortOrder FROM dbo.DurationUnits ORDER BY SortOrder;
    SELECT TimeConfidenceID, TimeConfidenceName, SortOrder FROM dbo.TimeConfidences ORDER BY SortOrder;
    SELECT ScenePurposeTypeID, PurposeName, SortOrder FROM dbo.ScenePurposeTypes WHERE IsArchived = 0 ORDER BY SortOrder;
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;
END;
GO
