SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

IF OBJECT_ID(N'dbo.CharacterRoleInSceneTypes', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.CharacterRoleInSceneTypes
    (
        CharacterRoleInSceneTypeID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_CharacterRoleInSceneTypes PRIMARY KEY,
        TypeName nvarchar(100) NOT NULL,
        SortOrder int NOT NULL,
        IsActive bit NOT NULL CONSTRAINT DF_CharacterRoleInSceneTypes_IsActive DEFAULT 1,
        CONSTRAINT UQ_CharacterRoleInSceneTypes_TypeName UNIQUE (TypeName)
    );
END;
GO

IF OBJECT_ID(N'dbo.PresenceTypes', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.PresenceTypes
    (
        PresenceTypeID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_PresenceTypes PRIMARY KEY,
        TypeName nvarchar(100) NOT NULL,
        SortOrder int NOT NULL,
        IsActive bit NOT NULL CONSTRAINT DF_PresenceTypes_IsActive DEFAULT 1,
        CONSTRAINT UQ_PresenceTypes_TypeName UNIQUE (TypeName)
    );
END;
GO

IF OBJECT_ID(N'dbo.Characters', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.Characters
    (
        CharacterID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_Characters PRIMARY KEY,
        ProjectID int NOT NULL,
        CharacterName nvarchar(200) NOT NULL,
        ShortName nvarchar(100) NULL,
        Sex nvarchar(50) NULL,
        BirthDate date NULL,
        AgeAtSeriesStart int NULL,
        AgeReferenceSceneID int NULL,
        Height nvarchar(50) NULL,
        EyeColour nvarchar(50) NULL,
        CharacterImportance int NULL,
        DefaultDescription nvarchar(max) NULL,
        CreatedDate datetime2 NOT NULL CONSTRAINT DF_Characters_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2 NOT NULL CONSTRAINT DF_Characters_UpdatedDate DEFAULT SYSUTCDATETIME(),
        IsArchived bit NOT NULL CONSTRAINT DF_Characters_IsArchived DEFAULT 0,
        CONSTRAINT FK_Characters_Projects FOREIGN KEY (ProjectID) REFERENCES dbo.Projects(ProjectID),
        CONSTRAINT FK_Characters_AgeReferenceScene FOREIGN KEY (AgeReferenceSceneID) REFERENCES dbo.Scenes(SceneID)
    );
END;
GO

IF OBJECT_ID(N'dbo.SceneCharacters', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.SceneCharacters
    (
        SceneCharacterID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_SceneCharacters PRIMARY KEY,
        SceneID int NOT NULL,
        CharacterID int NOT NULL,
        RoleInSceneTypeID int NULL,
        PresenceTypeID int NULL,
        LocationID int NULL,
        EntryLocationID int NULL,
        ExitLocationID int NULL,
        AppearanceNotes nvarchar(max) NULL,
        OutfitDescription nvarchar(max) NULL,
        PhysicalCondition nvarchar(max) NULL,
        EmotionalState nvarchar(max) NULL,
        KnowledgeNotes nvarchar(max) NULL,
        CreatedDate datetime2 NOT NULL CONSTRAINT DF_SceneCharacters_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2 NOT NULL CONSTRAINT DF_SceneCharacters_UpdatedDate DEFAULT SYSUTCDATETIME(),
        CONSTRAINT FK_SceneCharacters_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID),
        CONSTRAINT FK_SceneCharacters_Characters FOREIGN KEY (CharacterID) REFERENCES dbo.Characters(CharacterID),
        CONSTRAINT FK_SceneCharacters_RoleTypes FOREIGN KEY (RoleInSceneTypeID) REFERENCES dbo.CharacterRoleInSceneTypes(CharacterRoleInSceneTypeID),
        CONSTRAINT FK_SceneCharacters_PresenceTypes FOREIGN KEY (PresenceTypeID) REFERENCES dbo.PresenceTypes(PresenceTypeID)
    );
END;
GO

IF OBJECT_ID(N'dbo.CharacterAttributeTypes', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.CharacterAttributeTypes
    (
        CharacterAttributeTypeID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_CharacterAttributeTypes PRIMARY KEY,
        ProjectID int NULL,
        AttributeName nvarchar(100) NOT NULL,
        DataType nvarchar(50) NOT NULL CONSTRAINT DF_CharacterAttributeTypes_DataType DEFAULT N'Text',
        IsNormallyStable bit NOT NULL CONSTRAINT DF_CharacterAttributeTypes_IsNormallyStable DEFAULT 0,
        SortOrder int NOT NULL,
        IsActive bit NOT NULL CONSTRAINT DF_CharacterAttributeTypes_IsActive DEFAULT 1,
        CONSTRAINT FK_CharacterAttributeTypes_Projects FOREIGN KEY (ProjectID) REFERENCES dbo.Projects(ProjectID)
    );
END;
GO

IF OBJECT_ID(N'dbo.CharacterAttributeEvents', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.CharacterAttributeEvents
    (
        CharacterAttributeEventID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_CharacterAttributeEvents PRIMARY KEY,
        CharacterID int NOT NULL,
        CharacterAttributeTypeID int NOT NULL,
        SceneID int NOT NULL,
        AttributeValue nvarchar(500) NOT NULL,
        Description nvarchar(max) NULL,
        CreatedDate datetime2 NOT NULL CONSTRAINT DF_CharacterAttributeEvents_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2 NOT NULL CONSTRAINT DF_CharacterAttributeEvents_UpdatedDate DEFAULT SYSUTCDATETIME(),
        CONSTRAINT FK_CharacterAttributeEvents_Characters FOREIGN KEY (CharacterID) REFERENCES dbo.Characters(CharacterID),
        CONSTRAINT FK_CharacterAttributeEvents_Types FOREIGN KEY (CharacterAttributeTypeID) REFERENCES dbo.CharacterAttributeTypes(CharacterAttributeTypeID),
        CONSTRAINT FK_CharacterAttributeEvents_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID)
    );
END;
GO

IF OBJECT_ID(N'dbo.KnowledgeStates', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.KnowledgeStates
    (
        KnowledgeStateID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_KnowledgeStates PRIMARY KEY,
        StateName nvarchar(100) NOT NULL,
        SortOrder int NOT NULL,
        IsActive bit NOT NULL CONSTRAINT DF_KnowledgeStates_IsActive DEFAULT 1,
        CONSTRAINT UQ_KnowledgeStates_StateName UNIQUE (StateName)
    );
END;
GO

IF OBJECT_ID(N'dbo.CharacterKnowledge', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.CharacterKnowledge
    (
        CharacterKnowledgeID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_CharacterKnowledge PRIMARY KEY,
        CharacterID int NOT NULL,
        StoryAssetID int NULL,
        PlotThreadID int NULL,
        SceneID int NOT NULL,
        KnowledgeStateID int NOT NULL,
        SourceEventID int NULL,
        Description nvarchar(max) NULL,
        CreatedDate datetime2 NOT NULL CONSTRAINT DF_CharacterKnowledge_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2 NOT NULL CONSTRAINT DF_CharacterKnowledge_UpdatedDate DEFAULT SYSUTCDATETIME(),
        CONSTRAINT FK_CharacterKnowledge_Characters FOREIGN KEY (CharacterID) REFERENCES dbo.Characters(CharacterID),
        CONSTRAINT FK_CharacterKnowledge_StoryAssets FOREIGN KEY (StoryAssetID) REFERENCES dbo.StoryAssets(StoryAssetID),
        CONSTRAINT FK_CharacterKnowledge_PlotThreads FOREIGN KEY (PlotThreadID) REFERENCES dbo.PlotThreads(PlotThreadID),
        CONSTRAINT FK_CharacterKnowledge_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID),
        CONSTRAINT FK_CharacterKnowledge_States FOREIGN KEY (KnowledgeStateID) REFERENCES dbo.KnowledgeStates(KnowledgeStateID)
    );
END;
GO

IF OBJECT_ID(N'dbo.RelationshipTypes', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.RelationshipTypes
    (
        RelationshipTypeID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_RelationshipTypes PRIMARY KEY,
        TypeName nvarchar(100) NOT NULL,
        IsPermanentDefault bit NOT NULL CONSTRAINT DF_RelationshipTypes_IsPermanentDefault DEFAULT 0,
        SortOrder int NOT NULL,
        IsActive bit NOT NULL CONSTRAINT DF_RelationshipTypes_IsActive DEFAULT 1,
        CONSTRAINT UQ_RelationshipTypes_TypeName UNIQUE (TypeName)
    );
END;
GO

IF OBJECT_ID(N'dbo.RelationshipStates', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.RelationshipStates
    (
        RelationshipStateID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_RelationshipStates PRIMARY KEY,
        StateName nvarchar(100) NOT NULL,
        SortOrder int NOT NULL,
        IsActive bit NOT NULL CONSTRAINT DF_RelationshipStates_IsActive DEFAULT 1,
        CONSTRAINT UQ_RelationshipStates_StateName UNIQUE (StateName)
    );
END;
GO

IF OBJECT_ID(N'dbo.CharacterRelationships', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.CharacterRelationships
    (
        CharacterRelationshipID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_CharacterRelationships PRIMARY KEY,
        ProjectID int NOT NULL,
        CharacterAID int NOT NULL,
        CharacterBID int NOT NULL,
        RelationshipTypeID int NOT NULL,
        IsPermanent bit NOT NULL CONSTRAINT DF_CharacterRelationships_IsPermanent DEFAULT 0,
        StartSceneID int NULL,
        EndSceneID int NULL,
        IsKnownToReader bit NOT NULL CONSTRAINT DF_CharacterRelationships_IsKnownToReader DEFAULT 0,
        Notes nvarchar(max) NULL,
        CreatedDate datetime2 NOT NULL CONSTRAINT DF_CharacterRelationships_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2 NOT NULL CONSTRAINT DF_CharacterRelationships_UpdatedDate DEFAULT SYSUTCDATETIME(),
        IsArchived bit NOT NULL CONSTRAINT DF_CharacterRelationships_IsArchived DEFAULT 0,
        CONSTRAINT FK_CharacterRelationships_Projects FOREIGN KEY (ProjectID) REFERENCES dbo.Projects(ProjectID),
        CONSTRAINT FK_CharacterRelationships_CharacterA FOREIGN KEY (CharacterAID) REFERENCES dbo.Characters(CharacterID),
        CONSTRAINT FK_CharacterRelationships_CharacterB FOREIGN KEY (CharacterBID) REFERENCES dbo.Characters(CharacterID),
        CONSTRAINT FK_CharacterRelationships_Types FOREIGN KEY (RelationshipTypeID) REFERENCES dbo.RelationshipTypes(RelationshipTypeID),
        CONSTRAINT FK_CharacterRelationships_StartScene FOREIGN KEY (StartSceneID) REFERENCES dbo.Scenes(SceneID),
        CONSTRAINT FK_CharacterRelationships_EndScene FOREIGN KEY (EndSceneID) REFERENCES dbo.Scenes(SceneID)
    );
END;
GO

IF OBJECT_ID(N'dbo.RelationshipEvents', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.RelationshipEvents
    (
        RelationshipEventID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_RelationshipEvents PRIMARY KEY,
        CharacterRelationshipID int NOT NULL,
        SceneID int NOT NULL,
        RelationshipStateID int NOT NULL,
        Intensity int NULL,
        IsKnownToOtherCharacter bit NOT NULL CONSTRAINT DF_RelationshipEvents_IsKnownToOtherCharacter DEFAULT 0,
        Description nvarchar(max) NULL,
        CreatedDate datetime2 NOT NULL CONSTRAINT DF_RelationshipEvents_CreatedDate DEFAULT SYSUTCDATETIME(),
        UpdatedDate datetime2 NOT NULL CONSTRAINT DF_RelationshipEvents_UpdatedDate DEFAULT SYSUTCDATETIME(),
        CONSTRAINT FK_RelationshipEvents_Relationships FOREIGN KEY (CharacterRelationshipID) REFERENCES dbo.CharacterRelationships(CharacterRelationshipID),
        CONSTRAINT FK_RelationshipEvents_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID),
        CONSTRAINT FK_RelationshipEvents_States FOREIGN KEY (RelationshipStateID) REFERENCES dbo.RelationshipStates(RelationshipStateID),
        CONSTRAINT CK_RelationshipEvents_Intensity CHECK (Intensity IS NULL OR Intensity BETWEEN 1 AND 10)
    );
END;
GO

IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Characters_ProjectID' AND object_id = OBJECT_ID(N'dbo.Characters'))
    CREATE INDEX IX_Characters_ProjectID ON dbo.Characters(ProjectID, IsArchived, CharacterName);
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_SceneCharacters_SceneID' AND object_id = OBJECT_ID(N'dbo.SceneCharacters'))
    CREATE INDEX IX_SceneCharacters_SceneID ON dbo.SceneCharacters(SceneID, CharacterID);
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_CharacterKnowledge_SceneID' AND object_id = OBJECT_ID(N'dbo.CharacterKnowledge'))
    CREATE INDEX IX_CharacterKnowledge_SceneID ON dbo.CharacterKnowledge(SceneID, CharacterID);
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_RelationshipEvents_SceneID' AND object_id = OBJECT_ID(N'dbo.RelationshipEvents'))
    CREATE INDEX IX_RelationshipEvents_SceneID ON dbo.RelationshipEvents(SceneID, CharacterRelationshipID);
GO

MERGE dbo.CharacterRoleInSceneTypes AS target
USING (VALUES
    (N'POV Character', 10), (N'Main Participant', 20), (N'Supporting Participant', 30), (N'Witness', 40),
    (N'Background', 50), (N'Mentioned Only', 60), (N'Hidden', 70), (N'Overhearing', 80)
) AS source (TypeName, SortOrder)
ON target.TypeName = source.TypeName
WHEN NOT MATCHED THEN INSERT (TypeName, SortOrder) VALUES (source.TypeName, source.SortOrder);
GO

MERGE dbo.PresenceTypes AS target
USING (VALUES
    (N'Present', 10), (N'Arrives', 20), (N'Leaves', 30), (N'Nearby', 40), (N'Hidden', 50),
    (N'Overhearing', 60), (N'Mentioned Only', 70), (N'Off-screen', 80), (N'Unknown', 90)
) AS source (TypeName, SortOrder)
ON target.TypeName = source.TypeName
WHEN NOT MATCHED THEN INSERT (TypeName, SortOrder) VALUES (source.TypeName, source.SortOrder);
GO

MERGE dbo.CharacterAttributeTypes AS target
USING (VALUES
    (N'Hair Colour', N'Text', 1, 10), (N'Hair Style', N'Text', 0, 20), (N'Injury', N'Text', 0, 30),
    (N'Disguise', N'Text', 0, 40), (N'Public Name', N'Text', 1, 50), (N'Mental State', N'Text', 0, 60),
    (N'Physical Condition', N'Text', 0, 70), (N'Reputation', N'Text', 0, 80), (N'Confidence', N'Number', 0, 90),
    (N'Clothing Note', N'Text', 0, 100)
) AS source (AttributeName, DataType, IsNormallyStable, SortOrder)
ON target.ProjectID IS NULL AND target.AttributeName = source.AttributeName
WHEN NOT MATCHED THEN INSERT (AttributeName, DataType, IsNormallyStable, SortOrder) VALUES (source.AttributeName, source.DataType, source.IsNormallyStable, source.SortOrder);
GO

MERGE dbo.KnowledgeStates AS target
USING (VALUES
    (N'Unaware', 10), (N'Suspects', 20), (N'Partially Knows', 30), (N'Knows', 40),
    (N'Misunderstands', 50), (N'Hiding', 60), (N'Lying About', 70)
) AS source (StateName, SortOrder)
ON target.StateName = source.StateName
WHEN NOT MATCHED THEN INSERT (StateName, SortOrder) VALUES (source.StateName, source.SortOrder);
GO

MERGE dbo.RelationshipTypes AS target
USING (VALUES
    (N'Parent', 1, 10), (N'Child', 1, 20), (N'Sibling', 1, 30), (N'Half-sibling', 1, 40),
    (N'Adoptive Parent', 1, 50), (N'Biological Parent', 1, 60), (N'Guardian', 1, 70),
    (N'Friend', 0, 80), (N'Enemy', 0, 90), (N'Lover', 0, 100), (N'Ex-lover', 0, 110),
    (N'Spouse', 1, 120), (N'Ally', 0, 130), (N'Rival', 0, 140), (N'Protector', 0, 150),
    (N'Suspicious Of', 0, 160), (N'Afraid Of', 0, 170), (N'Manipulating', 0, 180), (N'Estranged From', 0, 190)
) AS source (TypeName, IsPermanentDefault, SortOrder)
ON target.TypeName = source.TypeName
WHEN NOT MATCHED THEN INSERT (TypeName, IsPermanentDefault, SortOrder) VALUES (source.TypeName, source.IsPermanentDefault, source.SortOrder);
GO

MERGE dbo.RelationshipStates AS target
USING (VALUES
    (N'Unknown', 10), (N'Positive', 20), (N'Neutral', 30), (N'Negative', 40), (N'Tense', 50),
    (N'Friendly', 60), (N'Romantic', 70), (N'Sexual Tension', 80), (N'In Love', 90),
    (N'Distrustful', 100), (N'Hostile', 110), (N'Protective', 120), (N'Estranged', 130),
    (N'Broken', 140), (N'Reconciled', 150)
) AS source (StateName, SortOrder)
ON target.StateName = source.StateName
WHEN NOT MATCHED THEN INSERT (StateName, SortOrder) VALUES (source.StateName, source.SortOrder);
GO

CREATE OR ALTER PROCEDURE dbo.CharacterLookup_All
AS
BEGIN
    SET NOCOUNT ON;
    SELECT CharacterRoleInSceneTypeID, TypeName, SortOrder, IsActive FROM dbo.CharacterRoleInSceneTypes WHERE IsActive = 1 ORDER BY SortOrder;
    SELECT PresenceTypeID, TypeName, SortOrder, IsActive FROM dbo.PresenceTypes WHERE IsActive = 1 ORDER BY SortOrder;
    SELECT CharacterAttributeTypeID, ProjectID, AttributeName, DataType, IsNormallyStable, SortOrder, IsActive FROM dbo.CharacterAttributeTypes WHERE IsActive = 1 ORDER BY SortOrder;
    SELECT KnowledgeStateID, StateName, SortOrder, IsActive FROM dbo.KnowledgeStates WHERE IsActive = 1 ORDER BY SortOrder;
    SELECT RelationshipTypeID, TypeName, IsPermanentDefault, SortOrder, IsActive FROM dbo.RelationshipTypes WHERE IsActive = 1 ORDER BY SortOrder;
    SELECT RelationshipStateID, StateName, SortOrder, IsActive FROM dbo.RelationshipStates WHERE IsActive = 1 ORDER BY SortOrder;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Character_ListByProject
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT CharacterID, ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID,
        Height, EyeColour, CharacterImportance, DefaultDescription, CreatedDate, UpdatedDate, IsArchived
    FROM dbo.Characters
    WHERE ProjectID = @ProjectID AND IsArchived = 0
    ORDER BY CharacterName;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Character_Get
    @CharacterID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT CharacterID, ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID,
        Height, EyeColour, CharacterImportance, DefaultDescription, CreatedDate, UpdatedDate, IsArchived
    FROM dbo.Characters
    WHERE CharacterID = @CharacterID AND IsArchived = 0;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Character_Save
    @CharacterID int = NULL,
    @ProjectID int,
    @CharacterName nvarchar(200),
    @ShortName nvarchar(100) = NULL,
    @Sex nvarchar(50) = NULL,
    @BirthDate date = NULL,
    @AgeAtSeriesStart int = NULL,
    @AgeReferenceSceneID int = NULL,
    @Height nvarchar(50) = NULL,
    @EyeColour nvarchar(50) = NULL,
    @CharacterImportance int = NULL,
    @DefaultDescription nvarchar(max) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    IF @CharacterID IS NULL OR @CharacterID = 0
    BEGIN
        INSERT dbo.Characters (ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID, Height, EyeColour, CharacterImportance, DefaultDescription)
        VALUES (@ProjectID, @CharacterName, @ShortName, @Sex, @BirthDate, @AgeAtSeriesStart, @AgeReferenceSceneID, @Height, @EyeColour, @CharacterImportance, @DefaultDescription);
        SET @CharacterID = CAST(SCOPE_IDENTITY() AS int);
    END
    ELSE
    BEGIN
        UPDATE dbo.Characters
        SET CharacterName = @CharacterName, ShortName = @ShortName, Sex = @Sex, BirthDate = @BirthDate,
            AgeAtSeriesStart = @AgeAtSeriesStart, AgeReferenceSceneID = @AgeReferenceSceneID,
            Height = @Height, EyeColour = @EyeColour, CharacterImportance = @CharacterImportance, DefaultDescription = @DefaultDescription,
            UpdatedDate = SYSUTCDATETIME()
        WHERE CharacterID = @CharacterID;
    END
    SELECT @CharacterID;
END;
GO

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

CREATE OR ALTER PROCEDURE dbo.SceneCharacter_ListByScene
    @SceneID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT sc.SceneCharacterID, sc.SceneID, sc.CharacterID, c.ProjectID, c.CharacterName, c.ShortName, c.BirthDate, c.AgeAtSeriesStart,
        sc.RoleInSceneTypeID, role.TypeName AS RoleInSceneTypeName, sc.PresenceTypeID, presence.TypeName AS PresenceTypeName,
        sc.AppearanceNotes, sc.OutfitDescription, sc.PhysicalCondition, sc.EmotionalState, sc.KnowledgeNotes,
        sc.CreatedDate, sc.UpdatedDate
    FROM dbo.SceneCharacters sc
    INNER JOIN dbo.Characters c ON c.CharacterID = sc.CharacterID
    LEFT JOIN dbo.CharacterRoleInSceneTypes role ON role.CharacterRoleInSceneTypeID = sc.RoleInSceneTypeID
    LEFT JOIN dbo.PresenceTypes presence ON presence.PresenceTypeID = sc.PresenceTypeID
    WHERE sc.SceneID = @SceneID AND c.IsArchived = 0
    ORDER BY role.SortOrder, c.CharacterName;
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneCharacter_Save
    @SceneCharacterID int = NULL,
    @SceneID int,
    @CharacterID int,
    @RoleInSceneTypeID int = NULL,
    @PresenceTypeID int = NULL,
    @AppearanceNotes nvarchar(max) = NULL,
    @OutfitDescription nvarchar(max) = NULL,
    @PhysicalCondition nvarchar(max) = NULL,
    @EmotionalState nvarchar(max) = NULL,
    @KnowledgeNotes nvarchar(max) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    IF @SceneCharacterID IS NULL OR @SceneCharacterID = 0
    BEGIN
        SELECT @SceneCharacterID = SceneCharacterID FROM dbo.SceneCharacters WHERE SceneID = @SceneID AND CharacterID = @CharacterID;
    END
    IF @SceneCharacterID IS NULL OR @SceneCharacterID = 0
    BEGIN
        INSERT dbo.SceneCharacters (SceneID, CharacterID, RoleInSceneTypeID, PresenceTypeID, AppearanceNotes, OutfitDescription, PhysicalCondition, EmotionalState, KnowledgeNotes)
        VALUES (@SceneID, @CharacterID, @RoleInSceneTypeID, @PresenceTypeID, @AppearanceNotes, @OutfitDescription, @PhysicalCondition, @EmotionalState, @KnowledgeNotes);
        SET @SceneCharacterID = CAST(SCOPE_IDENTITY() AS int);
    END
    ELSE
    BEGIN
        UPDATE dbo.SceneCharacters
        SET CharacterID = @CharacterID, RoleInSceneTypeID = @RoleInSceneTypeID, PresenceTypeID = @PresenceTypeID,
            AppearanceNotes = @AppearanceNotes, OutfitDescription = @OutfitDescription, PhysicalCondition = @PhysicalCondition,
            EmotionalState = @EmotionalState, KnowledgeNotes = @KnowledgeNotes, UpdatedDate = SYSUTCDATETIME()
        WHERE SceneCharacterID = @SceneCharacterID;
    END
    SELECT @SceneCharacterID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.SceneCharacter_Delete
    @SceneCharacterID int
AS
BEGIN
    SET NOCOUNT ON;
    DELETE FROM dbo.SceneCharacters WHERE SceneCharacterID = @SceneCharacterID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterAttributeEvent_ListByCharacter
    @CharacterID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT cae.CharacterAttributeEventID, cae.CharacterID, c.CharacterName, cae.CharacterAttributeTypeID, cat.AttributeName,
        cae.SceneID, s.SceneNumber, s.SceneTitle, ch.ChapterNumber, b.BookTitle, cae.AttributeValue, cae.Description, cae.CreatedDate, cae.UpdatedDate
    FROM dbo.CharacterAttributeEvents cae
    INNER JOIN dbo.Characters c ON c.CharacterID = cae.CharacterID
    INNER JOIN dbo.CharacterAttributeTypes cat ON cat.CharacterAttributeTypeID = cae.CharacterAttributeTypeID
    INNER JOIN dbo.Scenes s ON s.SceneID = cae.SceneID
    INNER JOIN dbo.Chapters ch ON ch.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = ch.BookID
    WHERE cae.CharacterID = @CharacterID
    ORDER BY b.SortOrder, ch.SortOrder, s.SortOrder, cat.SortOrder;
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterAttributeEvent_Save
    @CharacterAttributeEventID int = NULL,
    @CharacterID int,
    @CharacterAttributeTypeID int,
    @SceneID int,
    @AttributeValue nvarchar(500),
    @Description nvarchar(max) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    IF @CharacterAttributeEventID IS NULL OR @CharacterAttributeEventID = 0
    BEGIN
        INSERT dbo.CharacterAttributeEvents (CharacterID, CharacterAttributeTypeID, SceneID, AttributeValue, Description)
        VALUES (@CharacterID, @CharacterAttributeTypeID, @SceneID, @AttributeValue, @Description);
        SET @CharacterAttributeEventID = CAST(SCOPE_IDENTITY() AS int);
    END
    ELSE
    BEGIN
        UPDATE dbo.CharacterAttributeEvents
        SET CharacterID = @CharacterID, CharacterAttributeTypeID = @CharacterAttributeTypeID, SceneID = @SceneID,
            AttributeValue = @AttributeValue, Description = @Description, UpdatedDate = SYSUTCDATETIME()
        WHERE CharacterAttributeEventID = @CharacterAttributeEventID;
    END
    SELECT @CharacterAttributeEventID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterKnowledge_ListByScene
    @SceneID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT ck.CharacterKnowledgeID, ck.CharacterID, c.CharacterName, ck.StoryAssetID, sa.AssetName, ck.PlotThreadID, pt.ThreadTitle,
        ck.SceneID, ck.KnowledgeStateID, ks.StateName AS KnowledgeStateName, ck.SourceEventID, ck.Description, ck.CreatedDate, ck.UpdatedDate
    FROM dbo.CharacterKnowledge ck
    INNER JOIN dbo.Characters c ON c.CharacterID = ck.CharacterID
    INNER JOIN dbo.KnowledgeStates ks ON ks.KnowledgeStateID = ck.KnowledgeStateID
    LEFT JOIN dbo.StoryAssets sa ON sa.StoryAssetID = ck.StoryAssetID
    LEFT JOIN dbo.PlotThreads pt ON pt.PlotThreadID = ck.PlotThreadID
    WHERE ck.SceneID = @SceneID
    ORDER BY c.CharacterName, ks.SortOrder;
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterKnowledge_ListByCharacter
    @CharacterID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT ck.CharacterKnowledgeID, ck.CharacterID, c.CharacterName, ck.StoryAssetID, sa.AssetName, ck.PlotThreadID, pt.ThreadTitle,
        ck.SceneID, s.SceneNumber, s.SceneTitle, ch.ChapterNumber, b.BookTitle,
        ck.KnowledgeStateID, ks.StateName AS KnowledgeStateName, ck.SourceEventID, ck.Description, ck.CreatedDate, ck.UpdatedDate
    FROM dbo.CharacterKnowledge ck
    INNER JOIN dbo.Characters c ON c.CharacterID = ck.CharacterID
    INNER JOIN dbo.KnowledgeStates ks ON ks.KnowledgeStateID = ck.KnowledgeStateID
    INNER JOIN dbo.Scenes s ON s.SceneID = ck.SceneID
    INNER JOIN dbo.Chapters ch ON ch.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = ch.BookID
    LEFT JOIN dbo.StoryAssets sa ON sa.StoryAssetID = ck.StoryAssetID
    LEFT JOIN dbo.PlotThreads pt ON pt.PlotThreadID = ck.PlotThreadID
    WHERE ck.CharacterID = @CharacterID
    ORDER BY b.SortOrder, ch.SortOrder, s.SortOrder;
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterKnowledge_Save
    @CharacterKnowledgeID int = NULL,
    @CharacterID int,
    @StoryAssetID int = NULL,
    @PlotThreadID int = NULL,
    @SceneID int,
    @KnowledgeStateID int,
    @SourceEventID int = NULL,
    @Description nvarchar(max) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    IF @CharacterKnowledgeID IS NULL OR @CharacterKnowledgeID = 0
    BEGIN
        INSERT dbo.CharacterKnowledge (CharacterID, StoryAssetID, PlotThreadID, SceneID, KnowledgeStateID, SourceEventID, Description)
        VALUES (@CharacterID, @StoryAssetID, @PlotThreadID, @SceneID, @KnowledgeStateID, @SourceEventID, @Description);
        SET @CharacterKnowledgeID = CAST(SCOPE_IDENTITY() AS int);
    END
    ELSE
    BEGIN
        UPDATE dbo.CharacterKnowledge
        SET CharacterID = @CharacterID, StoryAssetID = @StoryAssetID, PlotThreadID = @PlotThreadID, SceneID = @SceneID,
            KnowledgeStateID = @KnowledgeStateID, SourceEventID = @SourceEventID, Description = @Description, UpdatedDate = SYSUTCDATETIME()
        WHERE CharacterKnowledgeID = @CharacterKnowledgeID;
    END
    SELECT @CharacterKnowledgeID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Relationship_ListByCharacter
    @CharacterID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT cr.CharacterRelationshipID, cr.ProjectID, cr.CharacterAID, ca.CharacterName AS CharacterAName,
        cr.CharacterBID, cb.CharacterName AS CharacterBName, cr.RelationshipTypeID, rt.TypeName AS RelationshipTypeName,
        cr.IsPermanent, cr.StartSceneID, cr.EndSceneID, cr.IsKnownToReader, cr.Notes, cr.CreatedDate, cr.UpdatedDate, cr.IsArchived
    FROM dbo.CharacterRelationships cr
    INNER JOIN dbo.Characters ca ON ca.CharacterID = cr.CharacterAID
    INNER JOIN dbo.Characters cb ON cb.CharacterID = cr.CharacterBID
    INNER JOIN dbo.RelationshipTypes rt ON rt.RelationshipTypeID = cr.RelationshipTypeID
    WHERE cr.IsArchived = 0 AND @CharacterID IN (cr.CharacterAID, cr.CharacterBID)
    ORDER BY ca.CharacterName, cb.CharacterName, rt.SortOrder;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Relationship_ListByProject
    @ProjectID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT cr.CharacterRelationshipID, cr.ProjectID, cr.CharacterAID, ca.CharacterName AS CharacterAName,
        cr.CharacterBID, cb.CharacterName AS CharacterBName, cr.RelationshipTypeID, rt.TypeName AS RelationshipTypeName,
        cr.IsPermanent, cr.StartSceneID, cr.EndSceneID, cr.IsKnownToReader, cr.Notes, cr.CreatedDate, cr.UpdatedDate, cr.IsArchived
    FROM dbo.CharacterRelationships cr
    INNER JOIN dbo.Characters ca ON ca.CharacterID = cr.CharacterAID
    INNER JOIN dbo.Characters cb ON cb.CharacterID = cr.CharacterBID
    INNER JOIN dbo.RelationshipTypes rt ON rt.RelationshipTypeID = cr.RelationshipTypeID
    WHERE cr.ProjectID = @ProjectID AND cr.IsArchived = 0
    ORDER BY ca.CharacterName, cb.CharacterName, rt.SortOrder;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Relationship_Save
    @CharacterRelationshipID int = NULL,
    @ProjectID int,
    @CharacterAID int,
    @CharacterBID int,
    @RelationshipTypeID int,
    @IsPermanent bit,
    @StartSceneID int = NULL,
    @EndSceneID int = NULL,
    @IsKnownToReader bit,
    @Notes nvarchar(max) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    IF @CharacterRelationshipID IS NULL OR @CharacterRelationshipID = 0
    BEGIN
        INSERT dbo.CharacterRelationships (ProjectID, CharacterAID, CharacterBID, RelationshipTypeID, IsPermanent, StartSceneID, EndSceneID, IsKnownToReader, Notes)
        VALUES (@ProjectID, @CharacterAID, @CharacterBID, @RelationshipTypeID, @IsPermanent, @StartSceneID, @EndSceneID, @IsKnownToReader, @Notes);
        SET @CharacterRelationshipID = CAST(SCOPE_IDENTITY() AS int);
    END
    ELSE
    BEGIN
        UPDATE dbo.CharacterRelationships
        SET CharacterAID = @CharacterAID, CharacterBID = @CharacterBID, RelationshipTypeID = @RelationshipTypeID,
            IsPermanent = @IsPermanent, StartSceneID = @StartSceneID, EndSceneID = @EndSceneID,
            IsKnownToReader = @IsKnownToReader, Notes = @Notes, UpdatedDate = SYSUTCDATETIME()
        WHERE CharacterRelationshipID = @CharacterRelationshipID;
    END
    SELECT @CharacterRelationshipID;
END;
GO

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

CREATE OR ALTER PROCEDURE dbo.RelationshipEvent_ListByCharacter
    @CharacterID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT re.RelationshipEventID, re.CharacterRelationshipID, cr.ProjectID, cr.CharacterAID, ca.CharacterName AS CharacterAName,
        cr.CharacterBID, cb.CharacterName AS CharacterBName, rt.TypeName AS RelationshipTypeName,
        re.SceneID, s.SceneNumber, s.SceneTitle, ch.ChapterNumber, b.BookTitle,
        re.RelationshipStateID, rs.StateName AS RelationshipStateName, re.Intensity, re.IsKnownToOtherCharacter,
        re.Description, re.CreatedDate, re.UpdatedDate
    FROM dbo.RelationshipEvents re
    INNER JOIN dbo.CharacterRelationships cr ON cr.CharacterRelationshipID = re.CharacterRelationshipID
    INNER JOIN dbo.Characters ca ON ca.CharacterID = cr.CharacterAID
    INNER JOIN dbo.Characters cb ON cb.CharacterID = cr.CharacterBID
    INNER JOIN dbo.RelationshipTypes rt ON rt.RelationshipTypeID = cr.RelationshipTypeID
    INNER JOIN dbo.RelationshipStates rs ON rs.RelationshipStateID = re.RelationshipStateID
    INNER JOIN dbo.Scenes s ON s.SceneID = re.SceneID
    INNER JOIN dbo.Chapters ch ON ch.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = ch.BookID
    WHERE @CharacterID IN (cr.CharacterAID, cr.CharacterBID)
    ORDER BY b.SortOrder, ch.SortOrder, s.SortOrder;
END;
GO

CREATE OR ALTER PROCEDURE dbo.RelationshipEvent_ListByScene
    @SceneID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT re.RelationshipEventID, re.CharacterRelationshipID, cr.ProjectID, cr.CharacterAID, ca.CharacterName AS CharacterAName,
        cr.CharacterBID, cb.CharacterName AS CharacterBName, rt.TypeName AS RelationshipTypeName,
        re.SceneID, re.RelationshipStateID, rs.StateName AS RelationshipStateName, re.Intensity, re.IsKnownToOtherCharacter,
        re.Description, re.CreatedDate, re.UpdatedDate
    FROM dbo.RelationshipEvents re
    INNER JOIN dbo.CharacterRelationships cr ON cr.CharacterRelationshipID = re.CharacterRelationshipID
    INNER JOIN dbo.Characters ca ON ca.CharacterID = cr.CharacterAID
    INNER JOIN dbo.Characters cb ON cb.CharacterID = cr.CharacterBID
    INNER JOIN dbo.RelationshipTypes rt ON rt.RelationshipTypeID = cr.RelationshipTypeID
    INNER JOIN dbo.RelationshipStates rs ON rs.RelationshipStateID = re.RelationshipStateID
    WHERE re.SceneID = @SceneID
    ORDER BY ca.CharacterName, cb.CharacterName;
END;
GO

CREATE OR ALTER PROCEDURE dbo.RelationshipEvent_Save
    @RelationshipEventID int = NULL,
    @CharacterRelationshipID int,
    @SceneID int,
    @RelationshipStateID int,
    @Intensity int = NULL,
    @IsKnownToOtherCharacter bit,
    @Description nvarchar(max) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    IF @RelationshipEventID IS NULL OR @RelationshipEventID = 0
    BEGIN
        INSERT dbo.RelationshipEvents (CharacterRelationshipID, SceneID, RelationshipStateID, Intensity, IsKnownToOtherCharacter, Description)
        VALUES (@CharacterRelationshipID, @SceneID, @RelationshipStateID, @Intensity, @IsKnownToOtherCharacter, @Description);
        SET @RelationshipEventID = CAST(SCOPE_IDENTITY() AS int);
    END
    ELSE
    BEGIN
        UPDATE dbo.RelationshipEvents
        SET CharacterRelationshipID = @CharacterRelationshipID, SceneID = @SceneID, RelationshipStateID = @RelationshipStateID,
            Intensity = @Intensity, IsKnownToOtherCharacter = @IsKnownToOtherCharacter,
            Description = @Description, UpdatedDate = SYSUTCDATETIME()
        WHERE RelationshipEventID = @RelationshipEventID;
    END
    SELECT @RelationshipEventID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.CharacterTimeline_GetByProject
    @ProjectID int,
    @BookID int = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SELECT CharacterID, ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID,
        Height, EyeColour, CharacterImportance, DefaultDescription, CreatedDate, UpdatedDate, IsArchived
    FROM dbo.Characters
    WHERE ProjectID = @ProjectID AND IsArchived = 0
    ORDER BY ISNULL(CharacterImportance, 0) DESC, CharacterName;

    SELECT sc.SceneCharacterID, sc.SceneID, sc.CharacterID, c.ProjectID, c.CharacterName, c.ShortName, c.BirthDate, c.AgeAtSeriesStart,
        sc.RoleInSceneTypeID, role.TypeName AS RoleInSceneTypeName, sc.PresenceTypeID, presence.TypeName AS PresenceTypeName,
        sc.AppearanceNotes, sc.OutfitDescription, sc.PhysicalCondition, sc.EmotionalState, sc.KnowledgeNotes,
        sc.CreatedDate, sc.UpdatedDate
    FROM dbo.SceneCharacters sc
    INNER JOIN dbo.Characters c ON c.CharacterID = sc.CharacterID
    INNER JOIN dbo.Scenes s ON s.SceneID = sc.SceneID
    INNER JOIN dbo.Chapters ch ON ch.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = ch.BookID
    LEFT JOIN dbo.CharacterRoleInSceneTypes role ON role.CharacterRoleInSceneTypeID = sc.RoleInSceneTypeID
    LEFT JOIN dbo.PresenceTypes presence ON presence.PresenceTypeID = sc.PresenceTypeID
    WHERE c.ProjectID = @ProjectID AND c.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID)
    ORDER BY b.SortOrder, ch.SortOrder, s.SortOrder, c.CharacterName;
END;
GO

CREATE OR ALTER PROCEDURE dbo.AssetCustodyEvent_Save
    @AssetCustodyEventID int = NULL,
    @StoryAssetID int,
    @SceneID int,
    @AssetCustodyEventTypeID int,
    @Description nvarchar(max) = NULL,
    @CustodianNames nvarchar(max) = NULL,
    @CustodianCharacterIds nvarchar(max) = NULL,
    @CustodyRoleID int
AS
BEGIN
    SET NOCOUNT ON;

    IF @AssetCustodyEventID IS NULL OR @AssetCustodyEventID = 0
    BEGIN
        INSERT dbo.AssetCustodyEvents (StoryAssetID, SceneID, AssetCustodyEventTypeID, Description)
        VALUES (@StoryAssetID, @SceneID, @AssetCustodyEventTypeID, @Description);
        SET @AssetCustodyEventID = CAST(SCOPE_IDENTITY() AS int);
    END
    ELSE
    BEGIN
        UPDATE dbo.AssetCustodyEvents
        SET StoryAssetID = @StoryAssetID, SceneID = @SceneID, AssetCustodyEventTypeID = @AssetCustodyEventTypeID,
            Description = @Description, UpdatedDate = SYSUTCDATETIME()
        WHERE AssetCustodyEventID = @AssetCustodyEventID;
    END

    DELETE FROM dbo.AssetCustodyEventCharacters WHERE AssetCustodyEventID = @AssetCustodyEventID;

    INSERT dbo.AssetCustodyEventCharacters (AssetCustodyEventID, CharacterID, CharacterNameText, CustodyRoleID)
    SELECT @AssetCustodyEventID, TRY_CAST(value AS int), NULL, @CustodyRoleID
    FROM STRING_SPLIT(ISNULL(@CustodianCharacterIds, N''), N',')
    WHERE TRY_CAST(value AS int) IS NOT NULL;

    INSERT dbo.AssetCustodyEventCharacters (AssetCustodyEventID, CharacterNameText, CustodyRoleID)
    SELECT @AssetCustodyEventID, LTRIM(RTRIM(value)), @CustodyRoleID
    FROM STRING_SPLIT(REPLACE(ISNULL(@CustodianNames, N''), CHAR(10), N','), N',')
    WHERE LTRIM(RTRIM(value)) <> N'';

    SELECT @AssetCustodyEventID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.AssetCustodyEvent_ListByScene
    @SceneID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT ace.AssetCustodyEventID, ace.StoryAssetID, sa.AssetName, ace.SceneID,
        ace.AssetCustodyEventTypeID, acet.TypeName AS CustodyEventTypeName, ace.Description,
        STRING_AGG(CONCAT(COALESCE(c.CharacterName, aec.CharacterNameText), N' (', cr.RoleName, N')'), N', ') AS CustodianSummary,
        ace.CreatedDate, ace.UpdatedDate
    FROM dbo.AssetCustodyEvents ace
    INNER JOIN dbo.StoryAssets sa ON sa.StoryAssetID = ace.StoryAssetID
    INNER JOIN dbo.AssetCustodyEventTypes acet ON acet.AssetCustodyEventTypeID = ace.AssetCustodyEventTypeID
    LEFT JOIN dbo.AssetCustodyEventCharacters aec ON aec.AssetCustodyEventID = ace.AssetCustodyEventID
    LEFT JOIN dbo.Characters c ON c.CharacterID = aec.CharacterID
    LEFT JOIN dbo.CustodyRoles cr ON cr.CustodyRoleID = aec.CustodyRoleID
    WHERE ace.SceneID = @SceneID
    GROUP BY ace.AssetCustodyEventID, ace.StoryAssetID, sa.AssetName, ace.SceneID, ace.AssetCustodyEventTypeID, acet.TypeName, ace.Description, ace.CreatedDate, ace.UpdatedDate
    ORDER BY sa.AssetName, ace.AssetCustodyEventID;
END;
GO

CREATE OR ALTER PROCEDURE dbo.AssetCustodyEvent_ListByAsset
    @StoryAssetID int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT ace.AssetCustodyEventID, ace.StoryAssetID, sa.AssetName, ace.SceneID,
        ace.AssetCustodyEventTypeID, acet.TypeName AS CustodyEventTypeName, ace.Description,
        STRING_AGG(CONCAT(COALESCE(c.CharacterName, aec.CharacterNameText), N' (', cr.RoleName, N')'), N', ') AS CustodianSummary,
        ace.CreatedDate, ace.UpdatedDate, b.BookTitle, ch.ChapterNumber, s.SceneNumber, s.SceneTitle
    FROM dbo.AssetCustodyEvents ace
    INNER JOIN dbo.StoryAssets sa ON sa.StoryAssetID = ace.StoryAssetID
    INNER JOIN dbo.AssetCustodyEventTypes acet ON acet.AssetCustodyEventTypeID = ace.AssetCustodyEventTypeID
    INNER JOIN dbo.Scenes s ON s.SceneID = ace.SceneID
    INNER JOIN dbo.Chapters ch ON ch.ChapterID = s.ChapterID
    INNER JOIN dbo.Books b ON b.BookID = ch.BookID
    LEFT JOIN dbo.AssetCustodyEventCharacters aec ON aec.AssetCustodyEventID = ace.AssetCustodyEventID
    LEFT JOIN dbo.Characters c ON c.CharacterID = aec.CharacterID
    LEFT JOIN dbo.CustodyRoles cr ON cr.CustodyRoleID = aec.CustodyRoleID
    WHERE ace.StoryAssetID = @StoryAssetID
    GROUP BY ace.AssetCustodyEventID, ace.StoryAssetID, sa.AssetName, ace.SceneID, ace.AssetCustodyEventTypeID, acet.TypeName, ace.Description, ace.CreatedDate, ace.UpdatedDate, b.BookTitle, ch.ChapterNumber, s.SceneNumber, s.SceneTitle, b.SortOrder, ch.SortOrder, s.SortOrder
    ORDER BY b.SortOrder, ch.SortOrder, s.SortOrder, ace.AssetCustodyEventID;
END;
GO
