SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

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

    SELECT COUNT(1)
    FROM dbo.Projects p
    INNER JOIN dbo.ProjectUserAccess pua ON pua.ProjectID = p.ProjectID
    WHERE p.IsArchived = 0
        AND p.ProjectName = @ProjectName
        AND pua.UserID = @UserID
        AND pua.IsActive = 1;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Scene_UpdatePovCharacter
    @SceneID int,
    @POVCharacterID int
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE dbo.Scenes
    SET POVCharacterID = @POVCharacterID,
        UpdatedDate = SYSUTCDATETIME()
    WHERE SceneID = @SceneID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Import_LookupIds
AS
BEGIN
    SET NOCOUNT ON;

    SELECT
        (SELECT TOP (1) RevisionStatusID FROM dbo.RevisionStatuses WHERE StatusName = N'Planned' ORDER BY SortOrder) AS RevisionStatusID,
        (SELECT TOP (1) TimeModeID FROM dbo.TimeModes WHERE TimeModeName = N'Relative' ORDER BY SortOrder) AS TimeModeID,
        (SELECT TOP (1) TimeConfidenceID FROM dbo.TimeConfidences WHERE TimeConfidenceName = N'Unknown' ORDER BY SortOrder) AS TimeConfidenceID;

    SELECT LocationTypeID AS LookupID, TypeName FROM dbo.LocationTypes WHERE IsActive = 1;
    SELECT CharacterRoleInSceneTypeID AS LookupID, TypeName FROM dbo.CharacterRoleInSceneTypes WHERE IsActive = 1;
    SELECT PresenceTypeID AS LookupID, TypeName FROM dbo.PresenceTypes WHERE IsActive = 1;
    SELECT PlotLineTypeID AS LookupID, TypeName FROM dbo.PlotLineTypes WHERE IsActive = 1;
    SELECT PlotImportanceID AS LookupID, ImportanceName AS TypeName FROM dbo.PlotImportance WHERE IsActive = 1;
    SELECT ThreadTypeID AS LookupID, TypeName FROM dbo.ThreadTypes WHERE IsActive = 1;
    SELECT ThreadStatusID AS LookupID, StatusName FROM dbo.ThreadStatuses WHERE IsActive = 1;
    SELECT ThreadEventTypeID AS LookupID, TypeName FROM dbo.ThreadEventTypes WHERE IsActive = 1;
    SELECT SceneDependencyTypeID AS LookupID, TypeName FROM dbo.SceneDependencyTypes WHERE IsActive = 1;
    SELECT AssetKindID AS LookupID, KindName AS TypeName FROM dbo.AssetKinds WHERE IsActive = 1;
    SELECT AssetStateID AS LookupID, StateName AS TypeName FROM dbo.AssetStates WHERE IsActive = 1;
    SELECT AssetEventTypeID AS LookupID, TypeName FROM dbo.AssetEventTypes WHERE IsActive = 1;
    SELECT AssetCustodyEventTypeID AS LookupID, TypeName FROM dbo.AssetCustodyEventTypes WHERE IsActive = 1;
    SELECT CustodyRoleID AS LookupID, RoleName AS TypeName FROM dbo.CustodyRoles WHERE IsActive = 1;
END;
GO

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

    SELECT BookID, Subtitle, Tagline, ShortDescription, Status, TargetWordCount, WritingStartDate, TargetCompletionDate, PublicationDate,
        CoverThumbnailPath, CoverStandardPath
    FROM dbo.Books
    WHERE ProjectID = @ProjectID;
END;
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
    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.ContinuityWarning_ListDashboardUnresolved
    @ProjectID int,
    @Count int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT TOP (@Count)
        cw.ContinuityWarningID,
        cw.ValidationRunID,
        cw.ProjectID,
        cw.BookID,
        b.BookTitle,
        b.Subtitle AS BookSubtitle,
        cw.ChapterID,
        c.ChapterNumber,
        c.ChapterTitle,
        cw.SceneID,
        s.SceneNumber,
        s.SceneTitle,
        cw.EntityType,
        cw.EntityID,
        cw.WarningTypeID,
        wt.TypeName AS WarningTypeName,
        cw.WarningSeverityID,
        ws.SeverityName,
        cw.Message,
        cw.Details,
        cw.IsDismissed,
        cw.IsIntentional,
        cw.CreatedDate,
        cw.LastDetectedDate
    FROM dbo.ContinuityWarnings cw
    INNER JOIN dbo.WarningTypes wt ON wt.WarningTypeID = cw.WarningTypeID
    INNER JOIN dbo.WarningSeverities ws ON ws.WarningSeverityID = cw.WarningSeverityID
    LEFT JOIN dbo.Books b ON b.BookID = cw.BookID
    LEFT JOIN dbo.Chapters c ON c.ChapterID = cw.ChapterID
    LEFT JOIN dbo.Scenes s ON s.SceneID = cw.SceneID
    WHERE cw.ProjectID = @ProjectID
        AND cw.IsDismissed = 0
        AND cw.IsIntentional = 0
    ORDER BY ws.SortOrder DESC, cw.LastDetectedDate DESC, cw.ContinuityWarningID DESC;
END;
GO

CREATE OR ALTER PROCEDURE dbo.WritingPlan_ListForManagement
    @UserID int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT wp.WritingPlanID, wp.UserID, wp.ProjectID, p.ProjectName, wp.BookID, b.BookTitle, b.Subtitle AS BookSubtitle,
        wp.PlanName, wp.GoalType, wp.StartDate, wp.DeadlineDate, wp.AvailableDaysJson, wp.SessionLengthMinutes, wp.IsActive,
        SUM(CASE WHEN wsi.ScheduleStatus = N'Planned' THEN 1 ELSE 0 END) AS PlannedTaskCount,
        MAX(CASE WHEN wsi.ScheduleStatus = N'Planned' THEN wsi.ScheduledDate ELSE NULL END) AS ProjectedFinishDate
    FROM dbo.WritingPlans wp
    INNER JOIN dbo.Projects p ON p.ProjectID = wp.ProjectID
    LEFT JOIN dbo.Books b ON b.BookID = wp.BookID
    LEFT JOIN dbo.WritingScheduleItems wsi ON wsi.WritingPlanID = wp.WritingPlanID
    WHERE wp.UserID = @UserID
    GROUP BY wp.WritingPlanID, wp.UserID, wp.ProjectID, p.ProjectName, wp.BookID, b.BookTitle, b.Subtitle,
        wp.PlanName, wp.GoalType, wp.StartDate, wp.DeadlineDate, wp.AvailableDaysJson, wp.SessionLengthMinutes, wp.IsActive
    ORDER BY wp.IsActive DESC, wp.DeadlineDate, wp.PlanName, wp.WritingPlanID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.WritingScheduleScene_ListForPlanning
    @ProjectID int,
    @BookID int = NULL,
    @IncludeBlockedScenes bit = 0
AS
BEGIN
    SET NOCOUNT ON;

    SELECT s.SceneID, rs.StatusName AS RevisionStatusName, sw.EstimatedWordCount, sw.Priority,
        COALESCE(sw.IsBlocked, 0) AS IsBlocked, b.SortOrder AS BookSortOrder,
        c.SortOrder AS ChapterSortOrder, s.SortOrder AS SceneSortOrder
    FROM dbo.Projects p
    INNER JOIN dbo.Books b ON b.ProjectID = p.ProjectID AND b.IsArchived = 0
    INNER JOIN dbo.Chapters c ON c.BookID = b.BookID AND c.IsArchived = 0
    INNER JOIN dbo.Scenes s ON s.ChapterID = c.ChapterID AND s.IsArchived = 0
    INNER JOIN dbo.RevisionStatuses rs ON rs.RevisionStatusID = s.RevisionStatusID
    LEFT JOIN dbo.SceneWorkflow sw ON sw.SceneID = s.SceneID
    WHERE p.ProjectID = @ProjectID
        AND p.IsArchived = 0
        AND (@BookID IS NULL OR b.BookID = @BookID)
        AND rs.StatusName IN (N'Outlined', N'Needs Work', N'Revised')
        AND (@IncludeBlockedScenes = 1 OR COALESCE(sw.IsBlocked, 0) = 0)
    ORDER BY COALESCE(sw.Priority, 0) DESC, b.SortOrder, c.SortOrder, s.SortOrder, s.SceneID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.WritingScheduleItem_DeleteByPlan
    @WritingPlanID int
AS
BEGIN
    SET NOCOUNT ON;

    DELETE FROM dbo.WritingScheduleItems
    WHERE WritingPlanID = @WritingPlanID;
END;
GO

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

    SELECT wp.WritingPlanID, wp.UserID, wp.ProjectID, p.ProjectName, wp.BookID, b.BookTitle, b.Subtitle AS BookSubtitle,
        wp.PlanName, wp.DeadlineDate, wp.IsActive
    FROM dbo.WritingPlans wp
    INNER JOIN dbo.Projects p ON p.ProjectID = wp.ProjectID
    LEFT JOIN dbo.Books b ON b.BookID = wp.BookID
    WHERE wp.UserID = @UserID
        AND (@ProjectID IS NULL OR wp.ProjectID = @ProjectID)
    ORDER BY wp.IsActive DESC, wp.DeadlineDate, wp.PlanName, wp.WritingPlanID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.WritingSchedulePreview_ListByPlan
    @WritingPlanID int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT wsi.WritingScheduleItemID, wsi.WritingPlanID, wsi.SceneID, wsi.ScheduledDate, wsi.TaskType,
        b.BookTitle, b.Subtitle AS BookSubtitle, c.ChapterNumber, c.ChapterTitle, s.SceneNumber, s.SceneTitle,
        sw.Priority, wsi.EstimatedMinutes, wsi.TargetWords, wsi.ScheduleStatus, wsi.Notes,
        COALESCE(sw.IsBlocked, 0) AS IsBlocked
    FROM dbo.WritingScheduleItems wsi
    INNER JOIN dbo.Scenes s ON s.SceneID = wsi.SceneID
    INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = c.BookID
    LEFT JOIN dbo.SceneWorkflow sw ON sw.SceneID = s.SceneID
    WHERE wsi.WritingPlanID = @WritingPlanID
    ORDER BY wsi.ScheduledDate, wsi.WritingScheduleItemID;
END;
GO

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

    SELECT wsi.WritingScheduleItemID, wsi.WritingPlanID, wp.PlanName, wsi.SceneID, wsi.ScheduledDate, wsi.TaskType,
        b.BookTitle, b.Subtitle AS BookSubtitle, c.ChapterNumber, c.ChapterTitle, c.SortOrder AS ChapterSortOrder,
        s.SceneNumber, s.SceneTitle, s.SortOrder AS SceneSortOrder, sw.Priority, wsi.EstimatedMinutes,
        wsi.TargetWords, wsi.ScheduleStatus, COALESCE(sw.IsBlocked, 0) AS IsBlocked
    FROM dbo.WritingPlans wp
    INNER JOIN dbo.WritingScheduleItems wsi ON wsi.WritingPlanID = wp.WritingPlanID
    INNER JOIN dbo.Scenes s ON s.SceneID = wsi.SceneID
    INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = c.BookID
    LEFT JOIN dbo.SceneWorkflow sw ON sw.SceneID = s.SceneID
    WHERE wp.UserID = @UserID
        AND wp.IsActive = 1
        AND (@ProjectID IS NULL OR wp.ProjectID = @ProjectID)
    ORDER BY wsi.ScheduledDate, wsi.WritingScheduleItemID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.WritingScheduleItem_UpdatePlannedStatusForUser
    @WritingScheduleItemID int,
    @UserID int,
    @ScheduleStatus nvarchar(50),
    @CompletedDateUtc datetime2 = NULL
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE wsi
    SET ScheduleStatus = @ScheduleStatus,
        CompletedDateUtc = @CompletedDateUtc,
        ModifiedDateUtc = SYSUTCDATETIME()
    FROM dbo.WritingScheduleItems wsi
    INNER JOIN dbo.WritingPlans wp ON wp.WritingPlanID = wsi.WritingPlanID
    WHERE wsi.WritingScheduleItemID = @WritingScheduleItemID
        AND wp.UserID = @UserID
        AND wp.IsActive = 1
        AND wsi.ScheduleStatus = N'Planned';
END;
GO

CREATE OR ALTER PROCEDURE dbo.WritingPlanSummary_ListRequiringRebalance
    @UserID int,
    @Today date,
    @ProjectID int = NULL
AS
BEGIN
    SET NOCOUNT ON;

    SELECT wp.WritingPlanID, wp.UserID, wp.ProjectID, p.ProjectName, wp.BookID, b.BookTitle, b.Subtitle AS BookSubtitle,
        wp.PlanName, wp.DeadlineDate, wp.IsActive
    FROM dbo.WritingPlans wp
    INNER JOIN dbo.Projects p ON p.ProjectID = wp.ProjectID
    LEFT JOIN dbo.Books b ON b.BookID = wp.BookID
    WHERE wp.UserID = @UserID
        AND wp.IsActive = 1
        AND (@ProjectID IS NULL OR wp.ProjectID = @ProjectID)
        AND EXISTS
        (
            SELECT 1
            FROM dbo.WritingScheduleItems wsi
            WHERE wsi.WritingPlanID = wp.WritingPlanID
                AND wsi.ScheduleStatus = N'Planned'
                AND wsi.ScheduledDate < @Today
        )
    ORDER BY wp.DeadlineDate, wp.PlanName, wp.WritingPlanID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.WritingScheduleItem_UpdatePlannedDate
    @WritingPlanID int,
    @WritingScheduleItemID int,
    @ScheduledDate date
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE dbo.WritingScheduleItems
    SET ScheduledDate = @ScheduledDate,
        ModifiedDateUtc = SYSUTCDATETIME()
    WHERE WritingPlanID = @WritingPlanID
        AND WritingScheduleItemID = @WritingScheduleItemID
        AND ScheduleStatus = N'Planned';
END;
GO

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

    SELECT
        (SELECT COUNT(1) FROM dbo.Characters WHERE ProjectID = @ProjectID AND IsArchived = 0) AS CharacterCount,
        (SELECT COUNT(1) FROM dbo.Locations WHERE ProjectID = @ProjectID AND IsArchived = 0) AS LocationCount,
        (
            SELECT COUNT(1)
            FROM dbo.PlotThreads pt
            INNER JOIN dbo.PlotLines pl ON pl.PlotLineID = pt.PlotLineID
            INNER JOIN dbo.ThreadStatuses ts ON ts.ThreadStatusID = pt.ThreadStatusID
            WHERE pl.ProjectID = @ProjectID
                AND pl.IsArchived = 0
                AND pt.IsArchived = 0
                AND ts.IsOpenStatus = 1
        ) AS ActivePlotThreadCount,
        (
            SELECT COUNT(1)
            FROM dbo.ContinuityWarnings
            WHERE ProjectID = @ProjectID
                AND IsDismissed = 0
                AND IsIntentional = 0
        ) AS ContinuityWarningCount;
END;
GO

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

    SELECT TOP (@Count) pt.PlotThreadID, pt.ThreadTitle, pt.PlotLineID, pl.PlotLineName,
        pt.Importance, ts.StatusName AS ThreadStatusName, ts.IsOpenStatus, ts.IsResolvedStatus
    FROM dbo.PlotThreads pt
    INNER JOIN dbo.PlotLines pl ON pl.PlotLineID = pt.PlotLineID
    INNER JOIN dbo.ThreadStatuses ts ON ts.ThreadStatusID = pt.ThreadStatusID
    WHERE pl.ProjectID = @ProjectID
        AND pl.IsArchived = 0
        AND pt.IsArchived = 0
        AND (ts.StatusName = N'Dormant' OR (ts.IsOpenStatus = 1 AND pt.Importance >= 8))
    ORDER BY CASE WHEN ts.StatusName = N'Dormant' THEN 0 ELSE 1 END,
        pt.Importance DESC, pt.UpdatedDate DESC, pt.PlotThreadID DESC;
END;
GO

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

    SELECT TOP (@Count) pa.ProjectActivityID, pa.ProjectID, pa.UserID, u.DisplayName, u.Email,
        pa.ActivityType, pa.EntityType, pa.EntityID, pa.EntityName, pa.Description, pa.CreatedDateUTC
    FROM dbo.ProjectActivity pa
    LEFT JOIN dbo.AppUser u ON u.UserID = pa.UserID
    WHERE pa.ProjectID = @ProjectID
    ORDER BY pa.CreatedDateUTC DESC, pa.ProjectActivityID DESC;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Book_ListByProjects
    @ProjectIDs nvarchar(max)
AS
BEGIN
    SET NOCOUNT ON;

    ;WITH ProjectIDs AS
    (
        SELECT DISTINCT TRY_CONVERT(int, value) AS ProjectID
        FROM STRING_SPLIT(COALESCE(@ProjectIDs, N''), N',')
        WHERE TRY_CONVERT(int, value) IS NOT NULL
    )
    SELECT b.BookID, b.ProjectID, b.BookTitle, b.Subtitle, b.Tagline, b.ShortDescription, b.Status, b.BookNumber,
        b.Description, b.TargetWordCount, b.WritingStartDate, b.TargetCompletionDate, b.PublicationDate,
        b.CoverThumbnailPath, b.CoverStandardPath, ISNULL(wordCounts.CurrentWordCount, 0) AS CurrentWordCount,
        ISNULL(counts.ChapterCount, 0) AS ChapterCount, ISNULL(counts.SceneCount, 0) AS SceneCount,
        b.SortOrder, b.CreatedDate, b.UpdatedDate, b.IsArchived, b.ArchivedDate, b.ArchivedReason
    FROM dbo.Books b
    INNER JOIN ProjectIDs ids ON ids.ProjectID = b.ProjectID
    OUTER APPLY
    (
        SELECT COUNT(DISTINCT c.ChapterID) AS ChapterCount, COUNT(s.SceneID) AS SceneCount
        FROM dbo.Chapters c
        LEFT JOIN dbo.Scenes s ON s.ChapterID = c.ChapterID AND s.IsArchived = 0
        WHERE c.BookID = b.BookID AND c.IsArchived = 0
    ) counts
    OUTER APPLY
    (
        SELECT SUM(ISNULL(sw.ActualWordCount, 0)) AS CurrentWordCount
        FROM dbo.Chapters c
        INNER JOIN dbo.Scenes s ON s.ChapterID = c.ChapterID AND s.IsArchived = 0
        LEFT JOIN dbo.SceneWorkflow sw ON sw.SceneID = s.SceneID
        WHERE c.BookID = b.BookID AND c.IsArchived = 0
    ) wordCounts
    WHERE b.IsArchived = 0
    ORDER BY b.ProjectID, b.SortOrder, b.BookNumber, b.BookTitle;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Book_GetCoverPaths
    @BookID int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT BookID, ProjectID, CoverThumbnailPath, CoverStandardPath
    FROM dbo.Books
    WHERE BookID = @BookID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.ThreadEventTarget_ListByEvents
    @ThreadEventIDs nvarchar(max)
AS
BEGIN
    SET NOCOUNT ON;

    ;WITH ThreadEventIDs AS
    (
        SELECT DISTINCT TRY_CONVERT(int, value) AS ThreadEventID
        FROM STRING_SPLIT(COALESCE(@ThreadEventIDs, N''), N',')
        WHERE TRY_CONVERT(int, value) IS NOT NULL
    )
    SELECT petpl.PlotEventID, petpl.PlotLineID
    FROM dbo.PlotEventTargetPlotLines petpl
    INNER JOIN ThreadEventIDs ids ON ids.ThreadEventID = petpl.PlotEventID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.ThreadEventTarget_SaveForEvent
    @ThreadEventID int,
    @PlotLineIDs nvarchar(max) = NULL
AS
BEGIN
    SET NOCOUNT ON;

    DELETE FROM dbo.PlotEventTargetPlotLines
    WHERE PlotEventID = @ThreadEventID;

    ;WITH PlotLineIDs AS
    (
        SELECT DISTINCT TRY_CONVERT(int, value) AS PlotLineID
        FROM STRING_SPLIT(COALESCE(@PlotLineIDs, N''), N',')
        WHERE TRY_CONVERT(int, value) IS NOT NULL
            AND TRY_CONVERT(int, value) > 0
    )
    INSERT dbo.PlotEventTargetPlotLines (PlotEventID, PlotLineID)
    SELECT @ThreadEventID, PlotLineID
    FROM PlotLineIDs;
END;
GO

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

    SELECT acec.AssetCustodyEventID, ace.StoryAssetID, ace.SceneID, acec.CharacterID, c.CharacterName,
        acec.CharacterNameText, cr.RoleName, ace.UpdatedDate
    FROM dbo.AssetCustodyEventCharacters acec
    INNER JOIN dbo.AssetCustodyEvents ace ON ace.AssetCustodyEventID = acec.AssetCustodyEventID
    INNER JOIN dbo.StoryAssets sa ON sa.StoryAssetID = ace.StoryAssetID
    LEFT JOIN dbo.Characters c ON c.CharacterID = acec.CharacterID
    LEFT JOIN dbo.CustodyRoles cr ON cr.CustodyRoleID = acec.CustodyRoleID
    WHERE sa.ProjectID = @ProjectID
        AND sa.IsArchived = 0
        AND acec.CharacterID IS NOT NULL
        AND NULLIF(LTRIM(RTRIM(c.CharacterName)), N'') IS NOT NULL;
END;
GO

CREATE OR ALTER PROCEDURE dbo.AssetCustodySummary_ListByEvents
    @AssetCustodyEventIDs nvarchar(max)
AS
BEGIN
    SET NOCOUNT ON;

    ;WITH AssetCustodyEventIDs AS
    (
        SELECT DISTINCT TRY_CONVERT(int, value) AS AssetCustodyEventID
        FROM STRING_SPLIT(COALESCE(@AssetCustodyEventIDs, N''), N',')
        WHERE TRY_CONVERT(int, value) IS NOT NULL
    )
    SELECT acec.AssetCustodyEventID, c.CharacterName, cr.RoleName
    FROM dbo.AssetCustodyEventCharacters acec
    INNER JOIN AssetCustodyEventIDs ids ON ids.AssetCustodyEventID = acec.AssetCustodyEventID
    INNER JOIN dbo.Characters c ON c.CharacterID = acec.CharacterID
    LEFT JOIN dbo.CustodyRoles cr ON cr.CustodyRoleID = acec.CustodyRoleID
    WHERE acec.CharacterID IS NOT NULL
        AND NULLIF(LTRIM(RTRIM(c.CharacterName)), N'') IS NOT NULL;
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterSexValue_ListForOwner
    @OwnerUserID int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT CharacterSexValueID, OwnerUserID, SexName, IsSystem, SortOrder, IsActive
    FROM dbo.CharacterSexValues
    WHERE IsActive = 1
        AND (IsSystem = 1 OR OwnerUserID = @OwnerUserID)
    ORDER BY IsSystem DESC, SortOrder, SexName;
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterSexValue_Get
    @CharacterSexValueID int,
    @OwnerUserID int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT CharacterSexValueID, OwnerUserID, SexName, IsSystem, SortOrder, IsActive
    FROM dbo.CharacterSexValues
    WHERE CharacterSexValueID = @CharacterSexValueID
        AND IsActive = 1
        AND (IsSystem = 1 OR OwnerUserID = @OwnerUserID);
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterImage_ListByCharacter
    @CharacterID int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT CharacterImageID, CharacterID, ProjectID, ImagePath, ThumbnailPath, Caption, SortOrder, UploadedDateUTC, IsDeleted
    FROM dbo.CharacterImages
    WHERE CharacterID = @CharacterID
        AND IsDeleted = 0
    ORDER BY SortOrder, UploadedDateUTC, CharacterImageID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterImage_Get
    @CharacterImageID int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT CharacterImageID, CharacterID, ProjectID, ImagePath, ThumbnailPath, Caption, SortOrder, UploadedDateUTC, IsDeleted
    FROM dbo.CharacterImages
    WHERE CharacterImageID = @CharacterImageID
        AND IsDeleted = 0;
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterImage_Create
    @CharacterID int,
    @ProjectID int,
    @ImagePath nvarchar(500),
    @ThumbnailPath nvarchar(500) = NULL,
    @Caption nvarchar(500) = NULL,
    @InputSortOrder int = NULL
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @SortOrder int = COALESCE(@InputSortOrder, (SELECT ISNULL(MAX(SortOrder), 0) + 1 FROM dbo.CharacterImages WHERE CharacterID = @CharacterID));

    INSERT dbo.CharacterImages (CharacterID, ProjectID, ImagePath, ThumbnailPath, Caption, SortOrder)
    VALUES (@CharacterID, @ProjectID, @ImagePath, @ThumbnailPath, @Caption, @SortOrder);

    SELECT CAST(SCOPE_IDENTITY() AS int);
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterImage_Delete
    @CharacterImageID int
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE dbo.CharacterImages
    SET IsDeleted = 1,
        DeletedDateUTC = SYSUTCDATETIME()
    WHERE CharacterImageID = @CharacterImageID;
END;
GO
