SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

IF COL_LENGTH('dbo.SceneDependencies', 'ProjectID') IS NULL
BEGIN
    ALTER TABLE dbo.SceneDependencies ADD ProjectID int NULL;
END;
GO

UPDATE sd
SET ProjectID = b.ProjectID
FROM dbo.SceneDependencies sd
INNER JOIN dbo.Scenes s ON s.SceneID = sd.SourceSceneID
INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
INNER JOIN dbo.Books b ON b.BookID = c.BookID
WHERE sd.ProjectID IS NULL;
GO

IF COL_LENGTH('dbo.SceneDependencies', 'IsHardDependency') IS NULL
BEGIN
    ALTER TABLE dbo.SceneDependencies ADD IsHardDependency bit NOT NULL CONSTRAINT DF_SceneDependencies_IsHardDependency DEFAULT 0;
END;
GO

MERGE dbo.SceneDependencyTypes AS target
USING (VALUES
    (N'Must Occur Before', 10), (N'Emotional Setup', 20), (N'Reveal Setup', 30), (N'Action Consequence', 40),
    (N'Travel Dependency', 50), (N'Relationship Dependency', 60), (N'Knowledge Dependency', 70), (N'Object Dependency', 80),
    (N'Location Dependency', 90), (N'Time Dependency', 100)
) AS source (TypeName, SortOrder)
ON target.TypeName = source.TypeName
WHEN NOT MATCHED THEN INSERT (TypeName, SortOrder) VALUES (source.TypeName, source.SortOrder);
GO

CREATE OR ALTER PROCEDURE dbo.SceneDependencyLookup_All
AS
BEGIN
    SET NOCOUNT ON;
    SELECT SceneDependencyTypeID, TypeName, SortOrder, IsActive
    FROM dbo.SceneDependencyTypes
    WHERE IsActive = 1
    ORDER BY SortOrder;
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneDependency_Save
    @SceneDependencyID int = NULL,
    @ProjectID int = NULL,
    @SourceSceneID int,
    @TargetSceneID int,
    @SceneDependencyTypeID int,
    @Description nvarchar(max) = NULL,
    @IsHardDependency bit = 0
AS
BEGIN
    SET NOCOUNT ON;
    IF @ProjectID IS NULL
    BEGIN
        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 = @SourceSceneID;
    END;

    IF @SourceSceneID = @TargetSceneID
        RETURN;

    IF @SceneDependencyID IS NULL OR @SceneDependencyID = 0
    BEGIN
        INSERT dbo.SceneDependencies (ProjectID, SourceSceneID, TargetSceneID, SceneDependencyTypeID, Description, IsHardDependency)
        VALUES (@ProjectID, @SourceSceneID, @TargetSceneID, @SceneDependencyTypeID, @Description, @IsHardDependency);
        SELECT CAST(SCOPE_IDENTITY() AS int);
        RETURN;
    END;

    UPDATE dbo.SceneDependencies
    SET SourceSceneID = @SourceSceneID,
        TargetSceneID = @TargetSceneID,
        SceneDependencyTypeID = @SceneDependencyTypeID,
        Description = @Description,
        IsHardDependency = @IsHardDependency,
        UpdatedDate = SYSUTCDATETIME()
    WHERE SceneDependencyID = @SceneDependencyID;

    SELECT @SceneDependencyID;
END;
GO

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

CREATE OR ALTER PROCEDURE dbo.SceneDependency_ListByScene
    @SceneID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT sd.SceneDependencyID, sd.ProjectID, sd.SourceSceneID, sd.TargetSceneID, sd.SceneDependencyTypeID,
        sdt.TypeName AS SceneDependencyTypeName, sd.Description, sd.IsHardDependency, sd.CreatedDate, sd.UpdatedDate, sd.IsArchived,
        sourceOrder.BookID AS SourceBookID, sourceOrder.BookTitle AS SourceBookTitle, sourceOrder.ChapterID AS SourceChapterID,
        sourceOrder.ChapterNumber AS SourceChapterNumber, sourceOrder.SceneNumber AS SourceSceneNumber, sourceOrder.SceneTitle AS SourceSceneTitle,
        targetOrder.BookID AS TargetBookID, targetOrder.BookTitle AS TargetBookTitle, targetOrder.ChapterID AS TargetChapterID,
        targetOrder.ChapterNumber AS TargetChapterNumber, targetOrder.SceneNumber AS TargetSceneNumber, targetOrder.SceneTitle AS TargetSceneTitle,
        CASE WHEN sd.TargetSceneID = @SceneID THEN N'DependsOn' ELSE N'Dependent' END AS DependencyDirection
    FROM dbo.SceneDependencies sd
    INNER JOIN dbo.SceneDependencyTypes sdt ON sdt.SceneDependencyTypeID = sd.SceneDependencyTypeID
    INNER JOIN dbo.NarrativeSceneOrder sourceOrder ON sourceOrder.SceneID = sd.SourceSceneID
    INNER JOIN dbo.NarrativeSceneOrder targetOrder ON targetOrder.SceneID = sd.TargetSceneID
    WHERE sd.IsArchived = 0 AND @SceneID IN (sd.SourceSceneID, sd.TargetSceneID)
    ORDER BY DependencyDirection, sourceOrder.GlobalSceneIndex, targetOrder.GlobalSceneIndex;
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneDependency_ListByProject
    @ProjectID int,
    @BookID int = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SELECT sd.SceneDependencyID, sd.ProjectID, sd.SourceSceneID, sd.TargetSceneID, sd.SceneDependencyTypeID,
        sdt.TypeName AS SceneDependencyTypeName, sd.Description, sd.IsHardDependency, sd.CreatedDate, sd.UpdatedDate, sd.IsArchived,
        sourceOrder.BookID AS SourceBookID, sourceOrder.BookTitle AS SourceBookTitle, sourceOrder.ChapterID AS SourceChapterID,
        sourceOrder.ChapterNumber AS SourceChapterNumber, sourceOrder.SceneNumber AS SourceSceneNumber, sourceOrder.SceneTitle AS SourceSceneTitle,
        targetOrder.BookID AS TargetBookID, targetOrder.BookTitle AS TargetBookTitle, targetOrder.ChapterID AS TargetChapterID,
        targetOrder.ChapterNumber AS TargetChapterNumber, targetOrder.SceneNumber AS TargetSceneNumber, targetOrder.SceneTitle AS TargetSceneTitle
    FROM dbo.SceneDependencies sd
    INNER JOIN dbo.SceneDependencyTypes sdt ON sdt.SceneDependencyTypeID = sd.SceneDependencyTypeID
    INNER JOIN dbo.NarrativeSceneOrder sourceOrder ON sourceOrder.SceneID = sd.SourceSceneID
    INNER JOIN dbo.NarrativeSceneOrder targetOrder ON targetOrder.SceneID = sd.TargetSceneID
    WHERE sd.IsArchived = 0 AND sd.ProjectID = @ProjectID AND (@BookID IS NULL OR targetOrder.BookID = @BookID OR sourceOrder.BookID = @BookID)
    ORDER BY sourceOrder.GlobalSceneIndex, targetOrder.GlobalSceneIndex;
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneDependency_Counts
    @ProjectID int,
    @BookID int = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SELECT scene.SceneID, COUNT(*) AS DependencyCount
    FROM dbo.NarrativeSceneOrder scene
    INNER JOIN dbo.SceneDependencies sd ON scene.SceneID IN (sd.SourceSceneID, sd.TargetSceneID) AND sd.IsArchived = 0
    WHERE scene.ProjectID = @ProjectID AND (@BookID IS NULL OR scene.BookID = @BookID)
    GROUP BY scene.SceneID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.ChapterOption_ListByProject
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT c.ChapterID, b.BookID, b.BookTitle, b.BookNumber, c.ChapterNumber, c.ChapterTitle, c.SortOrder
    FROM dbo.Chapters c
    INNER JOIN dbo.Books b ON b.BookID = c.BookID
    WHERE b.ProjectID = @ProjectID AND b.IsArchived = 0 AND c.IsArchived = 0
    ORDER BY b.SortOrder, b.BookNumber, c.SortOrder, c.ChapterNumber;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Scene_NormalizeSortOrder
    @ChapterID int
AS
BEGIN
    SET NOCOUNT ON;
    ;WITH ordered AS
    (
        SELECT SceneID, ROW_NUMBER() OVER (ORDER BY SortOrder, SceneNumber, SceneID) AS rn
        FROM dbo.Scenes
        WHERE ChapterID = @ChapterID AND IsArchived = 0
    )
    UPDATE s
    SET SortOrder = ordered.rn * 10, UpdatedDate = SYSUTCDATETIME()
    FROM dbo.Scenes s
    INNER JOIN ordered ON ordered.SceneID = s.SceneID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Scene_RenumberChapter
    @ChapterID int
AS
BEGIN
    SET NOCOUNT ON;
    ;WITH ordered AS
    (
        SELECT SceneID, ROW_NUMBER() OVER (ORDER BY SortOrder, SceneNumber, SceneID) AS rn
        FROM dbo.Scenes
        WHERE ChapterID = @ChapterID AND IsArchived = 0
    )
    UPDATE s
    SET SceneNumber = ordered.rn, SortOrder = ordered.rn * 10, UpdatedDate = SYSUTCDATETIME()
    FROM dbo.Scenes s
    INNER JOIN ordered ON ordered.SceneID = s.SceneID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Chapter_RenumberBook
    @BookID int
AS
BEGIN
    SET NOCOUNT ON;
    ;WITH ordered AS
    (
        SELECT ChapterID, ROW_NUMBER() OVER (ORDER BY SortOrder, ChapterNumber, ChapterID) AS rn
        FROM dbo.Chapters
        WHERE BookID = @BookID AND IsArchived = 0
    )
    UPDATE c
    SET ChapterNumber = ordered.rn, SortOrder = ordered.rn * 10, UpdatedDate = SYSUTCDATETIME()
    FROM dbo.Chapters c
    INNER JOIN ordered ON ordered.ChapterID = c.ChapterID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneMovePreview_Get
    @SceneID int,
    @TargetChapterID int,
    @Position nvarchar(20) = N'End'
AS
BEGIN
    SET NOCOUNT ON;
    SELECT s.SceneID, s.SceneNumber, s.SceneTitle, s.ChapterID AS SourceChapterID, sourceChapter.ChapterNumber AS SourceChapterNumber,
        sourceChapter.ChapterTitle AS SourceChapterTitle, sourceBook.BookID AS SourceBookID, sourceBook.BookTitle AS SourceBookTitle,
        @TargetChapterID AS TargetChapterID, targetChapter.ChapterNumber AS TargetChapterNumber, targetChapter.ChapterTitle AS TargetChapterTitle,
        targetBook.BookID AS TargetBookID, targetBook.BookTitle AS TargetBookTitle, @Position AS Position,
        (SELECT COUNT(*) FROM dbo.SceneDependencies WHERE IsArchived = 0 AND @SceneID IN (SourceSceneID, TargetSceneID)) AS DependencyCount,
        (SELECT COUNT(*) FROM dbo.ContinuityWarnings WHERE IsDismissed = 0 AND IsIntentional = 0 AND SceneID = @SceneID) AS ActiveWarningCount
    FROM dbo.Scenes s
    INNER JOIN dbo.Chapters sourceChapter ON sourceChapter.ChapterID = s.ChapterID
    INNER JOIN dbo.Books sourceBook ON sourceBook.BookID = sourceChapter.BookID
    INNER JOIN dbo.Chapters targetChapter ON targetChapter.ChapterID = @TargetChapterID
    INNER JOIN dbo.Books targetBook ON targetBook.BookID = targetChapter.BookID
    WHERE s.SceneID = @SceneID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Scene_MoveToChapter
    @SceneID int,
    @TargetChapterID int,
    @Position nvarchar(20) = N'End',
    @Renumber bit = 0
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @SourceChapterID int = (SELECT ChapterID FROM dbo.Scenes WHERE SceneID = @SceneID);
    DECLARE @NewSortOrder int;

    IF @Position = N'Start'
        SELECT @NewSortOrder = ISNULL(MIN(SortOrder), 10) - 5 FROM dbo.Scenes WHERE ChapterID = @TargetChapterID AND IsArchived = 0;
    ELSE
        SELECT @NewSortOrder = ISNULL(MAX(SortOrder), 0) + 10 FROM dbo.Scenes WHERE ChapterID = @TargetChapterID AND IsArchived = 0 AND SceneID <> @SceneID;

    UPDATE dbo.Scenes
    SET ChapterID = @TargetChapterID, SortOrder = @NewSortOrder, UpdatedDate = SYSUTCDATETIME()
    WHERE SceneID = @SceneID;

    EXEC dbo.Scene_NormalizeSortOrder @SourceChapterID;
    EXEC dbo.Scene_NormalizeSortOrder @TargetChapterID;

    IF @Renumber = 1
    BEGIN
        EXEC dbo.Scene_RenumberChapter @SourceChapterID;
        EXEC dbo.Scene_RenumberChapter @TargetChapterID;
    END;

    SELECT @SceneID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneDependency_FinaliseWarnings
    @ProjectID int,
    @BookID int = NULL
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @ErrorSeverityID int = (SELECT WarningSeverityID FROM dbo.WarningSeverities WHERE SeverityName = N'Error');
    DECLARE @WarningSeverityID int = (SELECT WarningSeverityID FROM dbo.WarningSeverities WHERE SeverityName = N'Warning');
    DECLARE @WarningTypeID int = (SELECT WarningTypeID FROM dbo.WarningTypes WHERE TypeName = N'Scene Dependency Broken');

    UPDATE cw
    SET WarningSeverityID = CASE WHEN sd.IsHardDependency = 1 THEN @ErrorSeverityID ELSE @WarningSeverityID END,
        Message = CONCAT(N'Possible scene order issue: ''', sourceOrder.SceneTitle, N''' is now after ''', targetOrder.SceneTitle, N'''.'),
        Details = COALESCE(sd.Description, cw.Details),
        LastDetectedDate = SYSUTCDATETIME()
    FROM dbo.ContinuityWarnings cw
    INNER JOIN dbo.SceneDependencies sd ON sd.SceneDependencyID = cw.EntityID
    INNER JOIN dbo.NarrativeSceneOrder sourceOrder ON sourceOrder.SceneID = sd.SourceSceneID
    INNER JOIN dbo.NarrativeSceneOrder targetOrder ON targetOrder.SceneID = sd.TargetSceneID
    WHERE cw.ProjectID = @ProjectID
        AND cw.WarningTypeID = @WarningTypeID
        AND cw.EntityType = N'SceneDependency'
        AND (@BookID IS NULL OR cw.BookID = @BookID);
END;
GO
