-- AlterTable
ALTER TABLE "Item" ADD COLUMN     "subWeightedDownVotes" FLOAT NOT NULL DEFAULT 0,
ADD COLUMN     "subWeightedVotes" FLOAT NOT NULL DEFAULT 0;

CREATE INDEX "Item.sumSubVotes_index" ON "Item"(("subWeightedVotes" - "subWeightedDownVotes"));

-- CreateTable
CREATE TABLE "UserSubTrust" (
    "subName" CITEXT NOT NULL,
    "userId" INTEGER NOT NULL,
    "zapPostTrust" DOUBLE PRECISION NOT NULL DEFAULT 0,
    "subZapPostTrust" DOUBLE PRECISION NOT NULL DEFAULT 0,
    "zapCommentTrust" DOUBLE PRECISION NOT NULL DEFAULT 0,
    "subZapCommentTrust" DOUBLE PRECISION NOT NULL DEFAULT 0,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "UserSubTrust_pkey" PRIMARY KEY ("userId","subName")
);

-- AddForeignKey
ALTER TABLE "UserSubTrust" ADD CONSTRAINT "UserSubTrust_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "UserSubTrust" ADD CONSTRAINT "UserSubTrust_subName_fkey" FOREIGN KEY ("subName") REFERENCES "Sub"("name") ON DELETE CASCADE ON UPDATE CASCADE;

-- UserSubTrust is NOT populated, so this is a no-op ... but useful having it written out for migrating manually on deployment
UPDATE "Item"
SET "subWeightedVotes" = subquery."subWeightedVotes",
    "subWeightedDownVotes" = subquery."subWeightedDownVotes",
    "weightedVotes" = subquery."weightedVotes",
    "weightedDownVotes" = subquery."weightedDownVotes"
FROM (
    WITH sub_votes AS (
        SELECT "ItemAct"."itemId",
            CASE WHEN (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('TIP', 'FEE')))::FLOAT > 0
            THEN COALESCE(
                LOG(
                    (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('TIP', 'FEE')))::FLOAT / 1000
                ) * CASE
                        WHEN "Item"."parentId" IS NULL
                        THEN "UserSubTrust"."subZapPostTrust"
                        ELSE "UserSubTrust"."subZapCommentTrust"
                    END, 0)
            ELSE 0
            END AS "subWeightedVotes",
                        CASE WHEN (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('TIP', 'FEE')))::FLOAT > 0
            THEN COALESCE(
                LOG(
                    (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('TIP', 'FEE')))::FLOAT / 1000
                ) * CASE
                        WHEN "Item"."parentId" IS NULL
                        THEN "UserSubTrust"."zapPostTrust"
                        ELSE "UserSubTrust"."zapCommentTrust"
                    END, 0)
            ELSE 0
            END AS "weightedVotes",
            CASE WHEN (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('DONT_LIKE_THIS')))::FLOAT > 0
            THEN COALESCE(
                LOG(
                    (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('DONT_LIKE_THIS')))::FLOAT / 1000
                ) * CASE
                        WHEN "Item"."parentId" IS NULL
                        THEN "UserSubTrust"."subZapPostTrust"
                        ELSE "UserSubTrust"."subZapCommentTrust"
                    END, 0)
            ELSE 0
            END AS "subWeightedDownVotes",
            CASE WHEN (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('DONT_LIKE_THIS')))::FLOAT > 0
            THEN COALESCE(
                LOG(
                    (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('DONT_LIKE_THIS')))::FLOAT / 1000
                ) * CASE
                        WHEN "Item"."parentId" IS NULL
                        THEN "UserSubTrust"."zapPostTrust"
                        ELSE "UserSubTrust"."zapCommentTrust"
                    END, 0)
            ELSE 0
            END AS "weightedDownVotes"
            FROM "ItemAct"
            JOIN "UserSubTrust" ON "ItemAct"."userId" = "UserSubTrust"."userId"
            JOIN "Item" ON "Item".id = "ItemAct"."itemId"
                AND "UserSubTrust"."subName" = "Item"."subName"
                AND "Item"."userId" <> "ItemAct"."userId"
            WHERE "ItemAct".act IN ('TIP', 'FEE', 'DONT_LIKE_THIS')
            GROUP BY "ItemAct"."itemId", "ItemAct"."userId", "UserSubTrust"."subZapPostTrust",
            "UserSubTrust"."subZapCommentTrust", "UserSubTrust"."zapPostTrust", "UserSubTrust"."zapCommentTrust",
            "Item"."parentId"
    )
    SELECT "itemId", SUM("subWeightedVotes") AS "subWeightedVotes", SUM("subWeightedDownVotes") AS "subWeightedDownVotes",
        SUM("weightedVotes") AS "weightedVotes", SUM("weightedDownVotes") AS "weightedDownVotes"
    FROM sub_votes
    GROUP BY "itemId"
) AS subquery
WHERE "Item".id = subquery."itemId";

CREATE MATERIALIZED VIEW IF NOT EXISTS hot_score_view AS
  SELECT id,
         ("Item"."weightedVotes" - "Item"."weightedDownVotes" + ("Item"."weightedComments"*0.25) + ("Item".boost / 5000))
            / POWER(GREATEST(3, EXTRACT(EPOCH FROM (now() - "Item".created_at))/3600), 1.1) AS hot_score,
         ("Item"."subWeightedVotes" - "Item"."subWeightedDownVotes" + ("Item"."weightedComments"*0.25) + ("Item".boost / 5000))
            / POWER(GREATEST(3, EXTRACT(EPOCH FROM (now() - "Item".created_at))/3600), 1.1) AS sub_hot_score
  FROM "Item"
  WHERE "Item"."weightedVotes" > 0 OR "Item"."weightedDownVotes" > 0 OR "Item"."subWeightedVotes" > 0
    OR "Item"."subWeightedDownVotes" > 0 OR "Item"."weightedComments" > 0 OR "Item".boost > 0;

CREATE UNIQUE INDEX IF NOT EXISTS hot_score_view_id_idx ON hot_score_view(id);
CREATE INDEX IF NOT EXISTS hot_score_view_hot_score_idx ON hot_score_view(hot_score DESC NULLS LAST);
CREATE INDEX IF NOT EXISTS hot_score_view_sub_hot_score_idx ON hot_score_view(sub_hot_score DESC NULLS LAST);
