SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

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

    SELECT b.BookID AS BookId,
        b.BookTitle AS Title,
        b.Subtitle,
        b.SortOrder,
        b.UsesExplicitScenes
    FROM dbo.Books b
    INNER JOIN dbo.ProjectUserAccess pua ON pua.ProjectID = b.ProjectID
    INNER JOIN dbo.Projects p ON p.ProjectID = b.ProjectID
    WHERE b.ProjectID = @ProjectID
        AND pua.UserID = @UserID
        AND pua.IsActive = 1
        AND p.IsArchived = 0
        AND b.IsArchived = 0
    ORDER BY b.SortOrder, b.BookNumber, b.BookTitle, b.BookID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.WordCompanion_Book_Create
    @ProjectID int,
    @UserID int,
    @Title nvarchar(200)
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @TrimmedTitle nvarchar(200) = LTRIM(RTRIM(COALESCE(@Title, N'')));
    IF NULLIF(@TrimmedTitle, N'') IS NULL
        RETURN;

    IF NOT EXISTS
    (
        SELECT 1
        FROM dbo.Projects p
        INNER JOIN dbo.ProjectUserAccess pua ON pua.ProjectID = p.ProjectID
        WHERE p.ProjectID = @ProjectID
            AND p.IsArchived = 0
            AND pua.UserID = @UserID
            AND pua.IsActive = 1
    )
        RETURN;

    DECLARE @NextBookNumber int = ISNULL((SELECT MAX(BookNumber) FROM dbo.Books WHERE ProjectID = @ProjectID), 0) + 1;
    DECLARE @NextBookOrder int = ISNULL((SELECT MAX(SortOrder) FROM dbo.Books WHERE ProjectID = @ProjectID), 0) + 10;
    DECLARE @BookID int;

    INSERT dbo.Books (ProjectID, BookTitle, Status, BookNumber, SortOrder, UsesExplicitScenes)
    VALUES (@ProjectID, @TrimmedTitle, N'Planning', @NextBookNumber, @NextBookOrder, 0);

    SET @BookID = CAST(SCOPE_IDENTITY() AS int);

    SELECT @BookID AS BookId,
        @TrimmedTitle AS Title,
        CAST(NULL AS nvarchar(200)) AS Subtitle,
        @NextBookOrder AS SortOrder,
        CAST(0 AS bit) AS UsesExplicitScenes,
        N'Book created.' AS Message;
END;
GO

CREATE OR ALTER PROCEDURE dbo.WordCompanion_Manuscript_Analyse
    @UserID int,
    @ProjectID int,
    @BookID int,
    @DocumentGuid uniqueidentifier = NULL,
    @ChapterCount int,
    @SceneCount int,
    @WordCount int
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @ProjectTitle nvarchar(200);
    DECLARE @BookTitle nvarchar(200);
    DECLARE @BookSubtitle nvarchar(200);
    DECLARE @UsesExplicitScenes bit;

    SELECT @ProjectTitle = p.ProjectName,
        @BookTitle = b.BookTitle,
        @BookSubtitle = b.Subtitle,
        @UsesExplicitScenes = b.UsesExplicitScenes
    FROM dbo.Books b
    INNER JOIN dbo.Projects p ON p.ProjectID = b.ProjectID
    INNER JOIN dbo.ProjectUserAccess pua ON pua.ProjectID = p.ProjectID
    WHERE b.BookID = @BookID
        AND b.ProjectID = @ProjectID
        AND b.IsArchived = 0
        AND p.IsArchived = 0
        AND pua.UserID = @UserID
        AND pua.IsActive = 1;

    IF @BookTitle IS NULL
        RETURN;

    DECLARE @ExistingChapterCount int = (SELECT COUNT(*) FROM dbo.Chapters WHERE BookID = @BookID AND IsArchived = 0);
    DECLARE @ExistingSceneCount int =
    (
        SELECT COUNT(*)
        FROM dbo.Scenes s
        INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
        WHERE c.BookID = @BookID
            AND c.IsArchived = 0
            AND s.IsArchived = 0
    );
    DECLARE @LinkedChapterCount int =
    (
        SELECT COUNT(*)
        FROM dbo.Chapters
        WHERE BookID = @BookID
            AND IsArchived = 0
            AND IsLinkedToManuscript = 1
    );

    SELECT @ProjectID AS ProjectId,
        @BookID AS BookId,
        @ProjectTitle AS ProjectTitle,
        @BookTitle AS BookTitle,
        @BookSubtitle AS BookSubtitle,
        @UsesExplicitScenes AS UsesExplicitScenes,
        @ChapterCount AS ChapterCount,
        @SceneCount AS SceneCount,
        @WordCount AS WordCount,
        @ExistingChapterCount AS ExistingChapterCount,
        @ExistingSceneCount AS ExistingSceneCount,
        @LinkedChapterCount AS LinkedChapterCount,
        CAST(CASE WHEN @LinkedChapterCount = 0 AND @ChapterCount > 0 THEN 1 ELSE 0 END AS bit) AS CanImport,
        CAST(CASE WHEN @LinkedChapterCount = 0 AND @ExistingChapterCount > 0 THEN 1 ELSE 0 END AS bit) AS RequiresReplaceConfirmation,
        CASE
            WHEN @LinkedChapterCount > 0 THEN N'This Book already contains a linked manuscript.'
            WHEN @ChapterCount = 0 THEN N'No chapters were found. Use Heading 1 for chapter titles.'
            WHEN @ExistingChapterCount > 0 THEN N'This Book already contains planned chapters and scenes.'
            ELSE N'Ready to import manuscript structure.'
        END AS Message;
END;
GO

CREATE OR ALTER PROCEDURE dbo.WordCompanion_Manuscript_Import
    @UserID int,
    @ProjectID int,
    @BookID int,
    @DocumentGuid uniqueidentifier,
    @BindingVersion int = 1,
    @ReplacePlanned bit = 0,
    @StructureJson nvarchar(max)
AS
BEGIN
    SET NOCOUNT ON;
    SET XACT_ABORT ON;

    IF @DocumentGuid IS NULL OR @DocumentGuid = '00000000-0000-0000-0000-000000000000'
        SET @DocumentGuid = NEWID();

    DECLARE @BookTitle nvarchar(200);
    DECLARE @AccessProjectID int;

    SELECT @AccessProjectID = b.ProjectID,
        @BookTitle = b.BookTitle
    FROM dbo.Books b
    INNER JOIN dbo.Projects p ON p.ProjectID = b.ProjectID
    INNER JOIN dbo.ProjectUserAccess pua ON pua.ProjectID = p.ProjectID
    WHERE b.BookID = @BookID
        AND b.ProjectID = @ProjectID
        AND b.IsArchived = 0
        AND p.IsArchived = 0
        AND pua.UserID = @UserID
        AND pua.IsActive = 1;

    IF @BookTitle IS NULL
        RETURN;

    DECLARE @LinkedChapterCount int =
    (
        SELECT COUNT(*)
        FROM dbo.Chapters
        WHERE BookID = @BookID
            AND IsArchived = 0
            AND IsLinkedToManuscript = 1
    );

    IF @LinkedChapterCount > 0
    BEGIN
        SELECT CAST(0 AS bit) AS Imported,
            CAST(0 AS bit) AS RequiresReplaceConfirmation,
            N'This Book already contains a linked manuscript.' AS Message,
            @ProjectID AS ProjectId,
            @BookID AS BookId,
            0 AS ChaptersCreated,
            0 AS ScenesCreated,
            0 AS ArchivedChapters,
            0 AS ArchivedScenes;
        RETURN;
    END;

    DECLARE @ChapterCount int = (SELECT COUNT(*) FROM dbo.Chapters WHERE BookID = @BookID AND IsArchived = 0);
    IF @ChapterCount > 0 AND @ReplacePlanned = 0
    BEGIN
        SELECT CAST(0 AS bit) AS Imported,
            CAST(1 AS bit) AS RequiresReplaceConfirmation,
            N'This Book already contains planned chapters and scenes.' AS Message,
            @ProjectID AS ProjectId,
            @BookID AS BookId,
            0 AS ChaptersCreated,
            0 AS ScenesCreated,
            0 AS ArchivedChapters,
            0 AS ArchivedScenes;
        RETURN;
    END;

    DECLARE @Chapters table
    (
        ImportChapterIndex int NOT NULL PRIMARY KEY,
        Title nvarchar(200) NOT NULL,
        SortOrder int NOT NULL,
        WordCount int NOT NULL
    );

    DECLARE @Scenes table
    (
        ImportChapterIndex int NOT NULL,
        ImportSceneIndex int NOT NULL,
        Title nvarchar(200) NOT NULL,
        SortOrder int NOT NULL,
        WordCount int NOT NULL,
        PRIMARY KEY (ImportChapterIndex, ImportSceneIndex)
    );

    INSERT @Chapters (ImportChapterIndex, Title, SortOrder, WordCount)
    SELECT CONVERT(int, chapter.[key]) + 1,
        LEFT(LTRIM(RTRIM(JSON_VALUE(chapter.value, '$.Title'))), 200),
        TRY_CONVERT(int, JSON_VALUE(chapter.value, '$.SortOrder')),
        COALESCE(TRY_CONVERT(int, JSON_VALUE(chapter.value, '$.WordCount')), 0)
    FROM OPENJSON(@StructureJson) chapter
    WHERE NULLIF(LTRIM(RTRIM(JSON_VALUE(chapter.value, '$.Title'))), N'') IS NOT NULL;

    INSERT @Scenes (ImportChapterIndex, ImportSceneIndex, Title, SortOrder, WordCount)
    SELECT c.ImportChapterIndex,
        CONVERT(int, scene.[key]) + 1,
        LEFT(LTRIM(RTRIM(JSON_VALUE(scene.value, '$.Title'))), 200),
        TRY_CONVERT(int, JSON_VALUE(scene.value, '$.SortOrder')),
        COALESCE(TRY_CONVERT(int, JSON_VALUE(scene.value, '$.WordCount')), 0)
    FROM @Chapters c
    INNER JOIN OPENJSON(@StructureJson) chapter ON CONVERT(int, chapter.[key]) + 1 = c.ImportChapterIndex
    CROSS APPLY OPENJSON(chapter.value, '$.Scenes') scene
    WHERE NULLIF(LTRIM(RTRIM(JSON_VALUE(scene.value, '$.Title'))), N'') IS NOT NULL;

    IF NOT EXISTS (SELECT 1 FROM @Chapters)
        RETURN;

    IF EXISTS (SELECT 1 FROM @Chapters WHERE SortOrder IS NULL OR SortOrder <= 0 OR WordCount < 0)
        RETURN;

    IF EXISTS (SELECT 1 FROM @Scenes WHERE SortOrder IS NULL OR SortOrder <= 0 OR WordCount < 0)
        RETURN;

    IF EXISTS (SELECT 1 FROM @Chapters c WHERE NOT EXISTS (SELECT 1 FROM @Scenes s WHERE s.ImportChapterIndex = c.ImportChapterIndex))
        RETURN;

    DECLARE @PlannedRevisionStatusID int = (SELECT TOP (1) RevisionStatusID FROM dbo.RevisionStatuses WHERE StatusName = N'Planned' ORDER BY SortOrder);
    DECLARE @DefaultTimeModeID int = (SELECT TOP (1) TimeModeID FROM dbo.TimeModes ORDER BY CASE WHEN TimeModeName = N'Unknown' THEN 0 ELSE 1 END, SortOrder, TimeModeID);
    DECLARE @DefaultTimeConfidenceID int = (SELECT TOP (1) TimeConfidenceID FROM dbo.TimeConfidences ORDER BY CASE WHEN TimeConfidenceName = N'Unknown' THEN 0 ELSE 1 END, SortOrder, TimeConfidenceID);

    IF @PlannedRevisionStatusID IS NULL OR @DefaultTimeModeID IS NULL OR @DefaultTimeConfidenceID IS NULL
        RETURN;

    DECLARE @ImportChapterMap table
    (
        ImportChapterIndex int NOT NULL PRIMARY KEY,
        ChapterID int NOT NULL
    );

    DECLARE @ImportSceneMap table
    (
        ImportChapterIndex int NOT NULL,
        ImportSceneIndex int NOT NULL,
        SceneID int NOT NULL,
        PRIMARY KEY (ImportChapterIndex, ImportSceneIndex)
    );

    DECLARE @ArchivedChapters int = 0;
    DECLARE @ArchivedScenes int = 0;
    DECLARE @ManuscriptDocumentID int;
    DECLARE @LinkedUtc datetime2 = SYSUTCDATETIME();

    BEGIN TRANSACTION;

    IF @ChapterCount > 0
    BEGIN
        UPDATE s
        SET IsArchived = 1,
            ArchivedDate = SYSUTCDATETIME(),
            ArchivedReason = N'Replaced by Word Companion manuscript import',
            UpdatedDate = SYSUTCDATETIME()
        FROM dbo.Scenes s
        INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
        WHERE c.BookID = @BookID
            AND c.IsArchived = 0
            AND s.IsArchived = 0
            AND c.IsLinkedToManuscript = 0
            AND s.IsLinkedToManuscript = 0;

        SET @ArchivedScenes = @@ROWCOUNT;

        UPDATE dbo.Chapters
        SET IsArchived = 1,
            ArchivedDate = SYSUTCDATETIME(),
            ArchivedReason = N'Replaced by Word Companion manuscript import',
            UpdatedDate = SYSUTCDATETIME()
        WHERE BookID = @BookID
            AND IsArchived = 0
            AND IsLinkedToManuscript = 0;

        SET @ArchivedChapters = @@ROWCOUNT;
    END;

    IF EXISTS
    (
        SELECT 1
        FROM dbo.ManuscriptDocuments
        WHERE DocumentGuid = @DocumentGuid
            AND IsActive = 1
            AND BookID <> @BookID
    )
        THROW 51000, 'This manuscript document is already linked to another book.', 1;

    SELECT @ManuscriptDocumentID = ManuscriptDocumentID
    FROM dbo.ManuscriptDocuments
    WHERE BookID = @BookID
        AND IsActive = 1;

    IF @ManuscriptDocumentID IS NULL
    BEGIN
        INSERT dbo.ManuscriptDocuments (BookID, ProjectID, DocumentGuid, BindingVersion, CreatedByUserID, LastOpenedUtc, LastSyncUtc)
        VALUES (@BookID, @ProjectID, @DocumentGuid, @BindingVersion, @UserID, @LinkedUtc, @LinkedUtc);

        SET @ManuscriptDocumentID = CAST(SCOPE_IDENTITY() AS int);
    END
    ELSE
    BEGIN
        UPDATE dbo.ManuscriptDocuments
        SET DocumentGuid = @DocumentGuid,
            ProjectID = @ProjectID,
            BindingVersion = @BindingVersion,
            LastOpenedUtc = @LinkedUtc,
            LastSyncUtc = @LinkedUtc
        WHERE ManuscriptDocumentID = @ManuscriptDocumentID;
    END;

    DECLARE @ImportChapterIndex int;
    DECLARE @ChapterTitle nvarchar(200);
    DECLARE @ChapterSortOrder int;
    DECLARE @ChapterID int;
    DECLARE @ChapterNumber decimal(9,2);

    DECLARE chapter_cursor CURSOR LOCAL FAST_FORWARD FOR
        SELECT ImportChapterIndex, Title, SortOrder
        FROM @Chapters
        ORDER BY SortOrder, ImportChapterIndex;

    OPEN chapter_cursor;
    FETCH NEXT FROM chapter_cursor INTO @ImportChapterIndex, @ChapterTitle, @ChapterSortOrder;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @ChapterNumber = @ImportChapterIndex;

        INSERT dbo.Chapters
        (
            BookID, ChapterNumber, ChapterTitle, Summary, SortOrder, RevisionStatusID,
            IsLinkedToManuscript, ManuscriptDocumentID, ExternalReference, LinkedUtc
        )
        VALUES
        (
            @BookID, @ChapterNumber, @ChapterTitle, NULL, @ChapterSortOrder, @PlannedRevisionStatusID,
            1, @ManuscriptDocumentID, CONCAT(N'PD_CHAPTER_IMPORT_', @ImportChapterIndex), @LinkedUtc
        );

        SET @ChapterID = CAST(SCOPE_IDENTITY() AS int);
        INSERT @ImportChapterMap (ImportChapterIndex, ChapterID) VALUES (@ImportChapterIndex, @ChapterID);

        FETCH NEXT FROM chapter_cursor INTO @ImportChapterIndex, @ChapterTitle, @ChapterSortOrder;
    END;

    CLOSE chapter_cursor;
    DEALLOCATE chapter_cursor;

    DECLARE @ImportSceneIndex int;
    DECLARE @SceneTitle nvarchar(200);
    DECLARE @SceneSortOrder int;
    DECLARE @SceneWordCount int;
    DECLARE @SceneID int;

    DECLARE scene_cursor CURSOR LOCAL FAST_FORWARD FOR
        SELECT s.ImportChapterIndex, s.ImportSceneIndex, s.Title, s.SortOrder, s.WordCount, m.ChapterID
        FROM @Scenes s
        INNER JOIN @ImportChapterMap m ON m.ImportChapterIndex = s.ImportChapterIndex
        ORDER BY s.ImportChapterIndex, s.SortOrder, s.ImportSceneIndex;

    OPEN scene_cursor;
    FETCH NEXT FROM scene_cursor INTO @ImportChapterIndex, @ImportSceneIndex, @SceneTitle, @SceneSortOrder, @SceneWordCount, @ChapterID;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF @ImportSceneIndex = 1
        BEGIN
            SELECT TOP (1) @SceneID = SceneID
            FROM dbo.Scenes
            WHERE ChapterID = @ChapterID
                AND IsArchived = 0
            ORDER BY SortOrder, SceneID;

            UPDATE dbo.Scenes
            SET SceneNumber = @ImportSceneIndex,
                SceneTitle = @SceneTitle,
                SortOrder = @SceneSortOrder,
                IsLinkedToManuscript = 1,
                ManuscriptDocumentID = @ManuscriptDocumentID,
                ExternalReference = CONCAT(N'PD_SCENE_IMPORT_', @ImportChapterIndex, N'_', @ImportSceneIndex),
                LinkedUtc = @LinkedUtc,
                UpdatedDate = SYSUTCDATETIME()
            WHERE SceneID = @SceneID;
        END
        ELSE
        BEGIN
            INSERT dbo.Scenes
            (
                ChapterID, SceneNumber, SceneTitle, Summary, SortOrder, TimeModeID, TimeConfidenceID, RevisionStatusID,
                IsLinkedToManuscript, ManuscriptDocumentID, ExternalReference, LinkedUtc
            )
            VALUES
            (
                @ChapterID, @ImportSceneIndex, @SceneTitle, NULL, @SceneSortOrder, @DefaultTimeModeID, @DefaultTimeConfidenceID, @PlannedRevisionStatusID,
                1, @ManuscriptDocumentID, CONCAT(N'PD_SCENE_IMPORT_', @ImportChapterIndex, N'_', @ImportSceneIndex), @LinkedUtc
            );

            SET @SceneID = CAST(SCOPE_IDENTITY() AS int);
        END;

        IF EXISTS (SELECT 1 FROM dbo.SceneWorkflow WHERE SceneID = @SceneID)
        BEGIN
            UPDATE dbo.SceneWorkflow
            SET ActualWordCount = @SceneWordCount,
                UpdatedDate = SYSUTCDATETIME()
            WHERE SceneID = @SceneID;
        END
        ELSE
        BEGIN
            INSERT dbo.SceneWorkflow (SceneID, ActualWordCount)
            VALUES (@SceneID, @SceneWordCount);
        END;

        INSERT @ImportSceneMap (ImportChapterIndex, ImportSceneIndex, SceneID)
        VALUES (@ImportChapterIndex, @ImportSceneIndex, @SceneID);

        FETCH NEXT FROM scene_cursor INTO @ImportChapterIndex, @ImportSceneIndex, @SceneTitle, @SceneSortOrder, @SceneWordCount, @ChapterID;
    END;

    CLOSE scene_cursor;
    DEALLOCATE scene_cursor;

    COMMIT TRANSACTION;

    SELECT CAST(1 AS bit) AS Imported,
        CAST(0 AS bit) AS RequiresReplaceConfirmation,
        N'Manuscript structure imported.' AS Message,
        @ProjectID AS ProjectId,
        @BookID AS BookId,
        (SELECT COUNT(*) FROM @ImportChapterMap) AS ChaptersCreated,
        (SELECT COUNT(*) FROM @ImportSceneMap) AS ScenesCreated,
        @ArchivedChapters AS ArchivedChapters,
        @ArchivedScenes AS ArchivedScenes;

    SELECT md.ManuscriptDocumentID AS ManuscriptDocumentId,
        md.BookID AS BookId,
        md.ProjectID AS ProjectId,
        md.DocumentGuid,
        md.BindingVersion,
        md.CreatedUtc,
        md.LastSyncUtc,
        md.LastOpenedUtc,
        md.IsActive
    FROM dbo.ManuscriptDocuments md
    WHERE md.ManuscriptDocumentID = @ManuscriptDocumentID;
END;
GO
