
CREATE OR REPLACE PROCEDURE tcg.public.USP_TCG_MTG_Game_Session_Member_Save (
      a_comment TEXT
    , a_guid UUID
    , a_user_id INT
	, OUT o_success BOOLEAN
)
LANGUAGE plpgsql
AS $$
DECLARE
	v_bad_data_error_type_id INT;
	v_change_set_id INT;
	-- v_error_message TEXT;
	v_time_start TIMESTAMP;
	v_warning_error_type_id INT;
BEGIN
	v_bad_data_error_type_id := (SELECT ERROR_TYPE.error_type_id FROM tcg.public.Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = 'BAD_DATA' LIMIT 1);
	v_warning_error_type_id := (SELECT ERROR_TYPE.error_type_id FROM tcg.public.Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = 'WARNING' LIMIT 1);
	v_time_start := CURRENT_TIMESTAMP;
	
	DROP TABLE IF EXISTS Temp_User_Relationship_Save_Game;
	DROP TABLE IF EXISTS Temp_User_Relationship_Save_User;
	DROP TABLE IF EXISTS Temp_User_Relationship_Save_Session_Member;
	DROP TABLE IF EXISTS Temp_User_Relationship_Save_Error;
        
    CREATE TEMP TABLE Temp_User_Relationship_Save_Game (
          game_id INT NOT NULL
        , notes TEXT
        , is_commander BOOLEAN
        , is_draft BOOLEAN
        , is_sealed BOOLEAN
        , location_name TEXT
        , start_on TIMESTAMP
        , end_on TIMESTAMP
        , active BOOLEAN
        , created_on TIMESTAMP
        , created_by_user_id INT
        , updated_last_on TIMESTAMP
        , updated_last_by_user_id INT
        , change_set_id INT
    );
        
    CREATE TEMP TABLE Temp_User_Relationship_Save_User (
          user_id INT NOT NULL
        , user_auth0_id TEXT
        , firstname TEXT
        , surname TEXT
        , email TEXT
        , is_email_verified BOOLEAN
        , is_super_user BOOLEAN
        , active BOOLEAN
        , created_on TIMESTAMP
        , created_by_user_id INT
        , updated_last_on TIMESTAMP
        , updated_last_by_user_id INT
        , change_set_id INT
    );

    CREATE TEMP TABLE Temp_User_Relationship_Save_Session_Member (
          temp_id INT NOT NULL
        , member_id INT
        , game_id INT
        , user_id INT
        , is_permitted BOOLEAN
        , active BOOLEAN
        , created_on TIMESTAMP
        , created_by_user_id INT
        , updated_last_on TIMESTAMP
        , updated_last_by_user_id INT

        , is_new BOOLEAN
        , error_name TEXT
        , is_duplicate BOOLEAN
    );

	CREATE TEMP TABLE Temp_User_Relationship_Save_Error (
		  temp_id INT GENERATED ALWAYS AS IDENTITY
		, error_type_id INT
		, message TEXT
	);

	INSERT INTO Temp_User_Relationship_Save_Session_Member (
		  temp_id
        , member_id
        , game_id
        , user_id
        , is_permitted
        , active
        , created_on
        , created_by_user_id
        , updated_last_on
        , updated_last_by_user_id

		, is_new
		, error_name
	)
	SELECT
		  SESSION_MEMBER_T.temp_id
        , SESSION_MEMBER_T.member_id
        , SESSION_MEMBER_T.game_id
        , SESSION_MEMBER_T.user_id
        , COALESCE(SESSION_MEMBER_T.is_permitted, FALSE) -- is_permitted
        , COALESCE(SESSION_MEMBER_T.active, TRUE) -- active
        , COALESCE(SESSION_MEMBER_T.created_on, v_time_start) -- created_on
        , COALESCE(SESSION_MEMBER_T.created_by_user_id, a_user_id) -- created_by_user_id
        , COALESCE(SESSION_MEMBER_T.updated_last_on, v_time_start) -- updated_last_on
        , COALESCE(SESSION_MEMBER_T.updated_last_by_user_id, a_user_id) -- updated_last_by_user_id

		, CASE WHEN SESSION_MEMBER .member_id IS NULL THEN TRUE ELSE FALSE END AS is_new
		, CONCAT(
			  'Member { id: '
			, CAST(SESSION_MEMBER_T.member_id AS VARCHAR)
			, ', temp id: '
			, CAST(SESSION_MEMBER_T.temp_id AS VARCHAR)
			, ', game id: '
			, CAST(SESSION_MEMBER_T.game_id AS VARCHAR)
			, ', user id: '
			, CAST(SESSION_MEMBER_T.user_id AS VARCHAR)
			, ' }'
		) -- error_name
	FROM tcg.public.TCG_MTG_Game_Session_Member_Temp SESSION_MEMBER_T
	LEFT JOIN tcg.public.TCG_MTG_Game_Session_Member SESSION_MEMBER ON SESSION_MEMBER_T.member_id = SESSION_MEMBER.member_id
	WHERE SESSION_MEMBER_T.guid = a_guid
	;
	
    INSERT INTO Temp_User_Relationship_Save_Game (
          game_id
        , notes
        , is_commander
        , is_draft
        , is_sealed
        , location_name
        , start_on
        , end_on
        , active
        , created_on
        , created_by_user_id
        , updated_last_on
        , updated_last_by_user_id
        , change_set_id
    )
	SELECT DISTINCT
		  GAME.game_id
        , GAME.notes
        , GAME.is_commander
        , GAME.is_draft
        , GAME.is_sealed
        , GAME.location_name
        , GAME.start_on
        , GAME.end_on
        , GAME.active
        , GAME.created_on
        , GAME.created_by_user_id
        , GAME.updated_last_on
        , GAME.updated_last_by_user_id
        , GAME.change_set_id
	FROM tcg.public.TCG_MTG_Game GAME
	INNER JOIN Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T ON GAME.game_id = SESSION_MEMBER_T.game_id
	;

    INSERT INTO Temp_User_Relationship_Save_User (
          user_id
        , user_auth0_id
        , firstname
        , surname
        , email
        , is_email_verified
        , is_super_user
        , active
        , created_on
        , created_by_user_id
        , updated_last_on
        , updated_last_by_user_id
        , change_set_id
    )
	SELECT DISTINCT
          TCG_USER.user_id
        , TCG_USER.user_auth0_id
        , TCG_USER.firstname
        , TCG_USER.surname
        , TCG_USER.email
        , TCG_USER.is_email_verified
        , TCG_USER.is_super_user
        , TCG_USER.active
        , TCG_USER.created_on
        , TCG_USER.created_by_user_id
        , TCG_USER.updated_last_on
        , TCG_USER.updated_last_by_user_id
        , TCG_USER.change_set_id
	FROM tcg.public.TCG_User TCG_USER
	INNER JOIN Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T ON TCG_USER.user_id = SESSION_MEMBER_T.user_id
	;

	-- Missing fields
	WITH Session_Member_Missing_Field AS (
        SELECT
              SESSION_MEMBER_T.temp_id
            , 'game_id' AS field
        FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
        WHERE SESSION_MEMBER_T.game_id IS NULL
        UNION
        SELECT
              SESSION_MEMBER_T.temp_id
            , 'user_id' AS field
        FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
        WHERE SESSION_MEMBER_T.user_id IS NULL
    )
	INSERT INTO Temp_User_Relationship_Save_Error (
		  error_type_id
		, message
	)
	SELECT
		  v_bad_data_error_type_id -- error_type_id
		, CONCAT(
			'Missing mandatory field: '
			, SESSION_MEMBER_MISSING_FIELD.field
			, ' on '
			, SESSION_MEMBER_T.error_name
			, '.'
		) -- message
	FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
	INNER JOIN Session_Member_Missing_Field SESSION_MEMBER_MISSING_FIELD ON SESSION_MEMBER_T.temp_id = SESSION_MEMBER_MISSING_FIELD.temp_id
	;

	-- Failed join fields
	WITH Session_Member_Failed_Join_Field AS (
        SELECT
              SESSION_MEMBER_T.temp_id
            , 'game_id' AS field
        FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
        LEFT JOIN Temp_User_Relationship_Save_Game T_GAME ON SESSION_MEMBER_T.game_id = T_GAME.game_id
        WHERE T_GAME.game_id IS NULL
        UNION
        SELECT
              SESSION_MEMBER_T.temp_id
            , 'user_id' AS field
        FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
        LEFT JOIN Temp_User_Relationship_Save_User T_USER ON SESSION_MEMBER_T.user_id = T_USER.user_id
        WHERE T_USER.user_id IS NULL
    )
	INSERT INTO Temp_User_Relationship_Save_Error (
		  error_type_id
		, message
	)
	SELECT
		  v_bad_data_error_type_id -- error_type_id
		, CONCAT(
			'Failed relationship: '
			, SESSION_MEMBER_FAILED_JOIN_FIELD.field
			, ' on '
			, SESSION_MEMBER_T.error_name
			, '.'
		) -- message
	FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
	INNER JOIN Session_Member_Failed_Join_Field SESSION_MEMBER_FAILED_JOIN_FIELD ON SESSION_MEMBER_T.temp_id = SESSION_MEMBER_FAILED_JOIN_FIELD.temp_id
	;

	-- Duplicate Session Member
    -- By game and user
	WITH 
		  All_Session_Member AS (
			SELECT
				  SESSION_MEMBER_T.temp_id
                , SESSION_MEMBER_T.game_id
                , SESSION_MEMBER_T.user_id
                , TRUE AS is_save_record
			FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
            UNION
			SELECT
				  NULL AS temp_id
                , SESSION_MEMBER.game_id
                , SESSION_MEMBER.user_id
                , FALSE AS is_save_record
			FROM tcg.public.TCG_MTG_Game_Session_Member SESSION_MEMBER
            LEFT JOIN Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T ON SESSION_MEMBER.member_id = SESSION_MEMBER_T.member_id
            WHERE
                    SESSION_MEMBER_T.member_id IS NULL
                AND SESSION_MEMBER.active
		)
		, Session_Member_Count AS (
			SELECT
				  ALL_SESSION_MEMBER.game_id
                , ALL_SESSION_MEMBER.user_id
                , COUNT(*) AS count_members
			FROM All_Session_Member ALL_SESSION_MEMBER
            GROUP BY
                  ALL_SESSION_MEMBER.game_id
                , ALL_SESSION_MEMBER.user_id
		)
		, Duplicate_Session_Member AS (
			SELECT
				  ALL_SESSION_MEMBER.temp_id
                , ALL_SESSION_MEMBER.game_id
                , ALL_SESSION_MEMBER.user_id
                , CASE WHEN SESSION_MEMBER_COUNT.count_members = 1 THEN TRUE ELSE FALSE END AS is_unique_member
			FROM All_Session_Member ALL_SESSION_MEMBER
            INNER JOIN Session_Member_Count SESSION_MEMBER_COUNT
				ON 	ALL_SESSION_MEMBER.game_id = SESSION_MEMBER_COUNT.game_id
				AND ALL_SESSION_MEMBER.user_id = SESSION_MEMBER_COUNT.user_id
		)
	UPDATE Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
	SET is_duplicate = CASE WHEN NOT DUPLICATE_SESSION_MEMBER.is_unique_member THEN TRUE ELSE FALSE END
	FROM Duplicate_Session_Member DUPLICATE_SESSION_MEMBER
	WHERE SESSION_MEMBER_T.temp_id = DUPLICATE_SESSION_MEMBER.temp_id
	;
	
	IF EXISTS (
		SELECT *
		FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
		WHERE SESSION_MEMBER_T.is_duplicate
		LIMIT 1
	) THEN
		INSERT INTO Temp_User_Relationship_Save_Error (
			  error_type_id
			, message
		)
		SELECT
			  v_bad_data_error_type_id -- error_type_id
			, CONCAT(
				  'Duplicate on '
				, SESSION_MEMBER_T.error_name
			) -- message
		FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
		WHERE SESSION_MEMBER_T.is_duplicate
		;
	END IF;

	-- Nothing to save
	IF NOT EXISTS (SELECT * FROM Temp_User_Relationship_Save_Session_Member LIMIT 1) THEN
		INSERT INTO Temp_User_Relationship_Save_Error (
			  error_type_id
			, message
		)
		VALUES (
			  v_warning_error_type_id
			, 'Nothing to save.'
		);
	END IF;

	-- Outputs
	-- Change Set
	INSERT INTO tcg.public.TCG_Change_Set (
		  comment
		, updated_last_by_user_id
	)
	VALUES (
		  a_comment
		, a_user_id
	)
	RETURNING change_set_id INTO v_change_set_id
	;
	
	IF NOT EXISTS (SELECT * FROM Temp_User_Relationship_Save_Error T_ERROR WHERE T_ERROR.error_type_id <> v_warning_error_type_id LIMIT 1) THEN
		
		-- Session Member
		INSERT INTO tcg.public.TCG_MTG_Game_Session_Member (
              game_id
            , user_id
            , is_permitted
            , active
            , created_on
            , created_by_user_id
            , updated_last_on
            , updated_last_by_user_id
            , change_set_id
		)
		SELECT
			  SESSION_MEMBER_T.game_id
            , SESSION_MEMBER_T.user_id
            , SESSION_MEMBER_T.is_permitted
		    , SESSION_MEMBER_T.active
			, v_time_start -- created_on
			, a_user_id -- created_by_user_id
			, v_time_start -- updated_last_on
			, a_user_id -- updated_last_by_user_id
		    , v_change_set_id -- change_set_id
		FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
        LEFT JOIN Temp_User_Relationship_Save_Game T_GAME ON SESSION_MEMBER_T.game_id = T_GAME.game_id
		WHERE
				SESSION_MEMBER_T.is_new = TRUE
			AND SESSION_MEMBER_T.active = TRUE
        ORDER BY
              T_GAME.created_on
            , T_GAME.game_id
			, SESSION_MEMBER_T.is_permitted
            , SESSION_MEMBER_T.user_id
		;
	
		UPDATE tcg.public.TCG_MTG_Game_Session_Member SESSION_MEMBER
		SET
              game_id = SESSION_MEMBER_T.game_id
            , user_id = SESSION_MEMBER_T.user_id
            , is_permitted = SESSION_MEMBER_T.is_permitted
		    , active = SESSION_MEMBER_T.active
			, updated_last_on = v_time_start
			, updated_last_by_user_id = a_user_id
		    , change_set_id = v_change_set_id
		FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T
		WHERE
				SESSION_MEMBER.member_id = SESSION_MEMBER_T.member_id
			AND NOT SESSION_MEMBER_T.is_new
		;
	END IF;

	-- Error
	INSERT INTO tcg.public.Error (
		  guid
		, error_type_id
		, message
		, display_order
		, created_on
		, created_by_user_id
		, updated_last_on
		, updated_last_by_user_id
		, change_set_id
	)
	SELECT
		  a_guid
		, T_ERROR.error_type_id
		, T_ERROR.message
		, T_ERROR.temp_id
		, v_time_start
		, a_user_id
		, v_time_start
		, a_user_id
		, v_change_set_id
	FROM Temp_User_Relationship_Save_Error T_ERROR
	LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON T_ERROR.error_type_id = ERROR_TYPE.error_type_id
	ORDER BY T_ERROR.temp_id
	;

    COMMIT;
	
	o_success := NOT EXISTS (
		SELECT *
		FROM Temp_User_Relationship_Save_Error T_ERROR
		WHERE T_ERROR.error_type_id <> v_warning_error_type_id
		LIMIT 1
	);
	
	DELETE FROM tcg.public.TCG_MTG_Game_Session_Member_Temp SESSION_MEMBER_T WHERE SESSION_MEMBER_T.guid = a_guid;

	DROP TABLE IF EXISTS Temp_User_Relationship_Save_Game;
	DROP TABLE IF EXISTS Temp_User_Relationship_Save_User;
	DROP TABLE IF EXISTS Temp_User_Relationship_Save_Session_Member;
	DROP TABLE IF EXISTS Temp_User_Relationship_Save_Error;
END;
$$;


-- Call it with:
DO $$
DECLARE
	v_comment TEXT := 'MTG Game Session Member Save.';
	v_guid UUID;
    v_user_id INT := 3;
    v_success BOOLEAN;
BEGIN
	v_guid := gen_random_uuid();

	INSERT INTO tcg.public.TCG_MTG_Game_Session_Member_Temp (
		  guid
        , member_id
        , game_id
        , user_id
        , is_permitted
        , active
	)
	VALUES
          (
              v_guid
            , NULL -- member_id
            , 4 -- game_id
            , 3 -- user_id
            , TRUE -- is_permitted
            , TRUE -- active
        )
        , (
              v_guid
            , NULL -- member_id
            , 4 -- game_id
            , 4 -- user_id
            , FALSE -- is_permitted
            , TRUE -- active
        )
		/*
        , (
              v_guid
            , NULL -- member_id
            , 4 -- game_id
            , 3 -- user_id
            , FALSE -- is_permitted
            , TRUE -- active
        )
		*/
    ;

    CALL tcg.public.USP_TCG_MTG_Game_Session_Member_Save (
		  v_comment -- a_comment
		, v_guid -- a_guid
		, v_user_id -- a_user_id
		, v_success -- o_success
	);
    RAISE NOTICE 'Success: %', CASE WHEN v_success THEN 'TRUE' ELSE 'FALSE' END;
END;
$$;

SELECT *
-- DELETE
FROM tcg.public.Error ERROR
LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON ERROR.error_type_id = ERROR_TYPE.error_type_id
;
SELECT *
FROM tcg.public.Error_Type ERROR_TYPE
;
SELECT *
FROM tcg.public.TCG_Change_Set CHANGE_SET
ORDER BY CHANGE_SET.change_set_id  DESC
;

SELECT *
-- DELETE
FROM tcg.public.TCG_MTG_Game_Session_Member_Temp
;
SELECT *
-- DELETE
FROM tcg.public.TCG_MTG_Game_Session_Member SESSION_MEMBER
LEFT JOIN tcg.public.TCG_MTG_Game GAME ON SESSION_MEMBER.game_id = GAME.game_id
;



