SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

IF OBJECT_ID(N'dbo.RelationshipCategories', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.RelationshipCategories
    (
        RelationshipCategoryID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_RelationshipCategories PRIMARY KEY,
        CategoryName nvarchar(100) NOT NULL,
        SortOrder int NOT NULL,
        IsActive bit NOT NULL CONSTRAINT DF_RelationshipCategories_IsActive DEFAULT 1,
        CONSTRAINT UQ_RelationshipCategories_CategoryName UNIQUE(CategoryName)
    );
END;
GO

MERGE dbo.RelationshipCategories AS target
USING (VALUES
    (N'Family', 10),
    (N'Friendship', 20),
    (N'Romantic / Sexual', 30),
    (N'Hostile / Conflict', 40),
    (N'Professional / Social', 50),
    (N'Other', 900)
) AS source (CategoryName, SortOrder)
ON target.CategoryName = source.CategoryName
WHEN MATCHED THEN UPDATE SET SortOrder = source.SortOrder, IsActive = 1
WHEN NOT MATCHED THEN INSERT (CategoryName, SortOrder) VALUES (source.CategoryName, source.SortOrder);
GO

IF COL_LENGTH(N'dbo.RelationshipTypes', N'RelationshipCategoryID') IS NULL
BEGIN
    ALTER TABLE dbo.RelationshipTypes
        ADD RelationshipCategoryID int NULL;
END;
GO

IF COL_LENGTH(N'dbo.RelationshipTypes', N'RelationshipCategoryID') IS NOT NULL
    AND NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = N'FK_RelationshipTypes_Categories')
BEGIN
    ALTER TABLE dbo.RelationshipTypes
        ADD CONSTRAINT FK_RelationshipTypes_Categories FOREIGN KEY (RelationshipCategoryID) REFERENCES dbo.RelationshipCategories(RelationshipCategoryID);
END;
GO

UPDATE rt
SET RelationshipCategoryID = rc.RelationshipCategoryID
FROM dbo.RelationshipTypes rt
INNER JOIN
(
    VALUES
    (N'Parent', N'Family'), (N'Child', N'Family'), (N'Sibling', N'Family'), (N'Half-sibling', N'Family'),
    (N'Adoptive Parent', N'Family'), (N'Biological Parent', N'Family'), (N'Guardian', N'Family'),
    (N'Mother', N'Family'), (N'Father', N'Family'), (N'Sister', N'Family'), (N'Brother', N'Family'),
    (N'Cousin', N'Family'), (N'Aunt', N'Family'), (N'Uncle', N'Family'),
    (N'Friend', N'Friendship'), (N'Best Friend', N'Friendship'), (N'Ally', N'Friendship'), (N'Protector', N'Friendship'),
    (N'Lover', N'Romantic / Sexual'), (N'Ex-lover', N'Romantic / Sexual'), (N'Spouse', N'Romantic / Sexual'),
    (N'In Love', N'Romantic / Sexual'), (N'Romantic', N'Romantic / Sexual'), (N'Sexual Tension', N'Romantic / Sexual'),
    (N'Enemy', N'Hostile / Conflict'), (N'Rival', N'Hostile / Conflict'), (N'Hostile', N'Hostile / Conflict'),
    (N'Suspicious Of', N'Hostile / Conflict'), (N'Afraid Of', N'Hostile / Conflict'), (N'Estranged From', N'Hostile / Conflict'),
    (N'Manipulating', N'Hostile / Conflict'), (N'Distrustful', N'Hostile / Conflict'),
    (N'Colleague', N'Professional / Social'), (N'Employer', N'Professional / Social'), (N'Employee', N'Professional / Social'),
    (N'Boss', N'Professional / Social'), (N'Acquaintance', N'Professional / Social'), (N'Neighbour', N'Professional / Social'),
    (N'Landlord', N'Professional / Social'), (N'Tenant', N'Professional / Social'), (N'Teacher', N'Professional / Social'),
    (N'Student', N'Professional / Social'),
    (N'Unknown', N'Other'), (N'Stranger', N'Other'), (N'Other', N'Other')
) AS mapping (TypeName, CategoryName) ON mapping.TypeName = rt.TypeName
INNER JOIN dbo.RelationshipCategories rc ON rc.CategoryName = mapping.CategoryName;
GO

UPDATE rt
SET RelationshipCategoryID = otherCategory.RelationshipCategoryID
FROM dbo.RelationshipTypes rt
CROSS JOIN (SELECT RelationshipCategoryID FROM dbo.RelationshipCategories WHERE CategoryName = N'Other') otherCategory
WHERE rt.RelationshipCategoryID IS NULL;
GO

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

    SELECT RelationshipCategoryID, CategoryName, SortOrder, IsActive
    FROM dbo.RelationshipCategories
    WHERE IsActive = 1
    ORDER BY SortOrder, CategoryName;
END;
GO

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

    SELECT rt.RelationshipTypeID, rt.TypeName, rt.IsPermanentDefault, rt.SortOrder, rt.IsActive,
        rt.RelationshipCategoryID, rc.CategoryName AS RelationshipCategoryName, rc.SortOrder AS CategorySortOrder
    FROM dbo.RelationshipTypes rt
    LEFT JOIN dbo.RelationshipCategories rc ON rc.RelationshipCategoryID = rt.RelationshipCategoryID
    ORDER BY COALESCE(rc.SortOrder, 900), rt.SortOrder, rt.TypeName;
END;
GO

CREATE OR ALTER PROCEDURE dbo.RelationshipType_UpdateCategory
    @RelationshipTypeID int,
    @TypeName nvarchar(100),
    @RelationshipCategoryID int,
    @SortOrder int,
    @IsActive bit
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE dbo.RelationshipTypes
    SET TypeName = @TypeName,
        RelationshipCategoryID = @RelationshipCategoryID,
        SortOrder = @SortOrder,
        IsActive = @IsActive
    WHERE RelationshipTypeID = @RelationshipTypeID;
END;
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 rt.RelationshipTypeID, rt.TypeName, rt.IsPermanentDefault, rt.SortOrder, rt.IsActive,
        rt.RelationshipCategoryID, rc.CategoryName AS RelationshipCategoryName, rc.SortOrder AS CategorySortOrder
    FROM dbo.RelationshipTypes rt
    LEFT JOIN dbo.RelationshipCategories rc ON rc.RelationshipCategoryID = rt.RelationshipCategoryID
    WHERE rt.IsActive = 1
    ORDER BY COALESCE(rc.SortOrder, 900), rt.SortOrder, rt.TypeName;
    SELECT RelationshipStateID, StateName, SortOrder, IsActive FROM dbo.RelationshipStates WHERE IsActive = 1 ORDER BY SortOrder;
    SELECT RelationshipCategoryID, CategoryName, SortOrder, IsActive FROM dbo.RelationshipCategories WHERE IsActive = 1 ORDER BY SortOrder, CategoryName;
END;
GO

CREATE OR ALTER PROCEDURE dbo.Relationship_ListInitialByCharacter
    @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,
        rt.RelationshipCategoryID, rc.CategoryName AS RelationshipCategoryName, COALESCE(rc.SortOrder, 900) AS CategorySortOrder,
        rt.SortOrder AS RelationshipTypeSortOrder,
        cr.IsPermanent, cr.StartSceneID, cr.EndSceneID, cr.IsKnownToReader, cr.Notes,
        cr.IsInitialRelationship, cr.InitialBookID, b.BookTitle AS InitialBookTitle, cr.ReaderInitiallyKnows,
        cr.InitialRelationshipStateID, rs.StateName AS InitialRelationshipStateName, cr.InitialIntensity, cr.IsReciprocal,
        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
    LEFT JOIN dbo.RelationshipCategories rc ON rc.RelationshipCategoryID = rt.RelationshipCategoryID
    LEFT JOIN dbo.Books b ON b.BookID = cr.InitialBookID
    LEFT JOIN dbo.RelationshipStates rs ON rs.RelationshipStateID = cr.InitialRelationshipStateID
    WHERE cr.IsArchived = 0
        AND cr.IsInitialRelationship = 1
        AND @CharacterID IN (cr.CharacterAID, cr.CharacterBID)
    ORDER BY COALESCE(rc.SortOrder, 900), COALESCE(b.SortOrder, 0), rt.SortOrder, ca.CharacterName, cb.CharacterName;
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,
        rt.RelationshipCategoryID, rc.CategoryName AS RelationshipCategoryName, COALESCE(rc.SortOrder, 900) AS CategorySortOrder,
        rt.SortOrder AS RelationshipTypeSortOrder,
        cr.IsPermanent, cr.StartSceneID, cr.EndSceneID, cr.IsKnownToReader, cr.Notes,
        cr.IsInitialRelationship, cr.InitialBookID, b.BookTitle AS InitialBookTitle, cr.ReaderInitiallyKnows,
        cr.InitialRelationshipStateID, rs.StateName AS InitialRelationshipStateName, cr.InitialIntensity, cr.IsReciprocal,
        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
    LEFT JOIN dbo.RelationshipCategories rc ON rc.RelationshipCategoryID = rt.RelationshipCategoryID
    LEFT JOIN dbo.Books b ON b.BookID = cr.InitialBookID
    LEFT JOIN dbo.RelationshipStates rs ON rs.RelationshipStateID = cr.InitialRelationshipStateID
    WHERE cr.IsArchived = 0 AND @CharacterID IN (cr.CharacterAID, cr.CharacterBID)
    ORDER BY COALESCE(rc.SortOrder, 900), 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,
        rt.RelationshipCategoryID, rc.CategoryName AS RelationshipCategoryName, COALESCE(rc.SortOrder, 900) AS CategorySortOrder,
        rt.SortOrder AS RelationshipTypeSortOrder,
        cr.IsPermanent, cr.StartSceneID, cr.EndSceneID, cr.IsKnownToReader, cr.Notes,
        cr.IsInitialRelationship, cr.InitialBookID, b.BookTitle AS InitialBookTitle, cr.ReaderInitiallyKnows,
        cr.InitialRelationshipStateID, rs.StateName AS InitialRelationshipStateName, cr.InitialIntensity, cr.IsReciprocal,
        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
    LEFT JOIN dbo.RelationshipCategories rc ON rc.RelationshipCategoryID = rt.RelationshipCategoryID
    LEFT JOIN dbo.Books b ON b.BookID = cr.InitialBookID
    LEFT JOIN dbo.RelationshipStates rs ON rs.RelationshipStateID = cr.InitialRelationshipStateID
    WHERE cr.ProjectID = @ProjectID AND cr.IsArchived = 0
    ORDER BY COALESCE(rc.SortOrder, 900), ca.CharacterName, cb.CharacterName, rt.SortOrder;
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,
        rt.RelationshipCategoryID, rc.CategoryName AS RelationshipCategoryName, COALESCE(rc.SortOrder, 900) AS CategorySortOrder,
        rt.SortOrder AS RelationshipTypeSortOrder,
        cr.IsReciprocal, 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
    LEFT JOIN dbo.RelationshipCategories rc ON rc.RelationshipCategoryID = rt.RelationshipCategoryID
    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, re.CreatedDate, re.RelationshipEventID;
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,
        rt.RelationshipCategoryID, rc.CategoryName AS RelationshipCategoryName, COALESCE(rc.SortOrder, 900) AS CategorySortOrder,
        rt.SortOrder AS RelationshipTypeSortOrder,
        cr.IsReciprocal, 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
    LEFT JOIN dbo.RelationshipCategories rc ON rc.RelationshipCategoryID = rt.RelationshipCategoryID
    INNER JOIN dbo.RelationshipStates rs ON rs.RelationshipStateID = re.RelationshipStateID
    WHERE re.SceneID = @SceneID
    ORDER BY ca.CharacterName, cb.CharacterName, re.CreatedDate, re.RelationshipEventID;
END;
GO

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

    SELECT cr.CharacterRelationshipID,
        cr.CharacterAID,
        ca.CharacterName AS CharacterAName,
        cr.CharacterBID,
        cb.CharacterName AS CharacterBName,
        rt.TypeName AS RelationshipTypeName,
        rt.RelationshipCategoryID,
        rc.CategoryName AS RelationshipCategoryName,
        COALESCE(rc.SortOrder, 900) AS CategorySortOrder,
        rt.SortOrder AS RelationshipTypeSortOrder,
        CASE WHEN cr.IsInitialRelationship = 1 THEN rt.TypeName ELSE NULL END AS InitialRelationshipName,
        initialState.StateName AS InitialStateName,
        cr.InitialIntensity,
        COALESCE(currentEvent.StateName, initialState.StateName, rt.TypeName) AS CurrentStateName,
        COALESCE(currentEvent.Intensity, cr.InitialIntensity) AS CurrentIntensity,
        ISNULL(events.EventCount, 0) AS EventCount,
        firstEvent.SceneLabel AS FirstEventLabel,
        events.EventHistory
    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
    LEFT JOIN dbo.RelationshipCategories rc ON rc.RelationshipCategoryID = rt.RelationshipCategoryID
    LEFT JOIN dbo.RelationshipStates initialState ON initialState.RelationshipStateID = cr.InitialRelationshipStateID
    OUTER APPLY
    (
        SELECT TOP (1) rs.StateName, re.Intensity
        FROM dbo.RelationshipEvents re
        INNER JOIN dbo.RelationshipStates rs ON rs.RelationshipStateID = re.RelationshipStateID
        INNER JOIN dbo.Scenes s ON s.SceneID = re.SceneID AND s.IsArchived = 0
        INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID AND c.IsArchived = 0
        INNER JOIN dbo.Books b ON b.BookID = c.BookID AND b.IsArchived = 0
        WHERE re.CharacterRelationshipID = cr.CharacterRelationshipID
        ORDER BY b.SortOrder DESC, c.SortOrder DESC, s.SortOrder DESC, re.CreatedDate DESC, re.RelationshipEventID DESC
    ) currentEvent
    OUTER APPLY
    (
        SELECT COUNT(*) AS EventCount,
            STRING_AGG(
                CONVERT(nvarchar(max), CONCAT(b.BookTitle, N' / Ch ', c.ChapterNumber, N' / Scene ', s.SceneNumber, N': ', rs.StateName, N' [', ISNULL(eventCategory.CategoryName, N'Other'), N']', ISNULL(N' (' + CONVERT(nvarchar(20), re.Intensity) + N')', N''), ISNULL(N' - ' + re.Description, N''))),
                N' -> '
            ) WITHIN GROUP (ORDER BY b.SortOrder, c.SortOrder, s.SortOrder, re.CreatedDate, re.RelationshipEventID) AS EventHistory
        FROM dbo.RelationshipEvents re
        INNER JOIN dbo.CharacterRelationships eventRelationship ON eventRelationship.CharacterRelationshipID = re.CharacterRelationshipID
        INNER JOIN dbo.RelationshipTypes eventType ON eventType.RelationshipTypeID = eventRelationship.RelationshipTypeID
        LEFT JOIN dbo.RelationshipCategories eventCategory ON eventCategory.RelationshipCategoryID = eventType.RelationshipCategoryID
        INNER JOIN dbo.RelationshipStates rs ON rs.RelationshipStateID = re.RelationshipStateID
        INNER JOIN dbo.Scenes s ON s.SceneID = re.SceneID AND s.IsArchived = 0
        INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID AND c.IsArchived = 0
        INNER JOIN dbo.Books b ON b.BookID = c.BookID AND b.IsArchived = 0
        WHERE re.CharacterRelationshipID = cr.CharacterRelationshipID
    ) events
    OUTER APPLY
    (
        SELECT TOP (1) CONCAT(b.BookTitle, N' / Ch ', c.ChapterNumber, N' / Scene ', s.SceneNumber, N': ', s.SceneTitle) AS SceneLabel
        FROM dbo.RelationshipEvents re
        INNER JOIN dbo.Scenes s ON s.SceneID = re.SceneID AND s.IsArchived = 0
        INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID AND c.IsArchived = 0
        INNER JOIN dbo.Books b ON b.BookID = c.BookID AND b.IsArchived = 0
        WHERE re.CharacterRelationshipID = cr.CharacterRelationshipID
        ORDER BY b.SortOrder, c.SortOrder, s.SortOrder, re.CreatedDate, re.RelationshipEventID
    ) firstEvent
    WHERE cr.ProjectID = @ProjectID AND cr.IsArchived = 0
    ORDER BY COALESCE(rc.SortOrder, 900), ca.CharacterName, cb.CharacterName;
END;
GO
