-- =====================================================================
-- Migration 009: Tasks Module — Tasks with Reward System
-- =====================================================================


-- ---------------------------------------------------------------------
-- Block 1: Tasks Table
-- Stores community Tasks with Geometry, Moderation and Completion.
-- Status Flow: pending → rejected | open → completed → verified
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS tasks (
    task_id              SERIAL PRIMARY KEY,
    municipality_id      INTEGER NOT NULL REFERENCES municipalities(municipality_id),
    geom                 GEOMETRY(Geometry, 4326) NOT NULL,
    geom_type            VARCHAR(10) NOT NULL CHECK (geom_type IN ('point', 'line', 'polygon')),
    category             VARCHAR(50) NOT NULL,
    title                VARCHAR(200) NOT NULL,
    description          TEXT DEFAULT '',
    points_reward        INTEGER NOT NULL DEFAULT 25,
    author_name          VARCHAR(100) NOT NULL,
    browser_id           VARCHAR(36),
    photo_path           VARCHAR(255),
    status               VARCHAR(20) NOT NULL DEFAULT 'pending'
                         CHECK (status IN ('pending', 'rejected', 'open', 'completed', 'verified')),
    address              VARCHAR(255),

    -- Completion Fields (NULL until completed)
    completed_by_name    VARCHAR(100),
    completed_by_browser VARCHAR(36),
    completion_photo     VARCHAR(255),
    completion_comment   TEXT,
    completed_at         TIMESTAMP,

    -- Counters (updated via Triggers)
    likes_count          INTEGER NOT NULL DEFAULT 0,
    dislikes_count       INTEGER NOT NULL DEFAULT 0,
    comment_count        INTEGER NOT NULL DEFAULT 0,

    created_at           TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at           TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_tasks_municipality ON tasks(municipality_id);
CREATE INDEX idx_tasks_status ON tasks(status);
CREATE INDEX idx_tasks_category ON tasks(category);


-- ---------------------------------------------------------------------
-- Block 2: User Points Table
-- One Entry per verified Task Completion. Leaderboard via SUM/GROUP BY.
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS user_points (
    points_id            SERIAL PRIMARY KEY,
    municipality_id      INTEGER NOT NULL REFERENCES municipalities(municipality_id),
    user_name            VARCHAR(100) NOT NULL,
    points               INTEGER NOT NULL DEFAULT 25,
    task_id              INTEGER NOT NULL REFERENCES tasks(task_id) ON DELETE CASCADE,
    created_at           TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_user_points_municipality ON user_points(municipality_id);
CREATE INDEX idx_user_points_user ON user_points(user_name);


-- ---------------------------------------------------------------------
-- Block 3: Extends Votes Table for Tasks
-- Either contribution_id OR task_id is set, not both.
-- ---------------------------------------------------------------------
ALTER TABLE votes
    ADD COLUMN task_id INTEGER REFERENCES tasks(task_id) ON DELETE CASCADE;

CREATE INDEX idx_votes_task ON votes(task_id);

-- Unique Vote per Browser per Task
ALTER TABLE votes
    ADD CONSTRAINT votes_task_browser_unique
    UNIQUE (task_id, browser_id);


-- ---------------------------------------------------------------------
-- Block 4: Extends Comments Table for Tasks
-- Either contribution_id OR task_id is set, not both.
-- ---------------------------------------------------------------------
ALTER TABLE comments
    ADD COLUMN task_id INTEGER REFERENCES tasks(task_id) ON DELETE CASCADE;

CREATE INDEX idx_comments_task ON comments(task_id);


-- ---------------------------------------------------------------------
-- Block 5: Trigger — updated_at Timestamp for Tasks
-- ---------------------------------------------------------------------
CREATE TRIGGER set_tasks_updated_at
    BEFORE UPDATE ON tasks
    FOR EACH ROW
    EXECUTE FUNCTION set_updated_at();


-- ---------------------------------------------------------------------
-- Block 6: Trigger — Vote Counts for Tasks
-- Mirrors the Pattern from Contributions.
-- ---------------------------------------------------------------------
CREATE OR REPLACE FUNCTION update_task_vote_counts()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
        IF NEW.task_id IS NOT NULL THEN
            UPDATE tasks SET
                likes_count = (SELECT COUNT(*) FROM votes WHERE task_id = NEW.task_id AND vote_type = 'like'),
                dislikes_count = (SELECT COUNT(*) FROM votes WHERE task_id = NEW.task_id AND vote_type = 'dislike')
            WHERE task_id = NEW.task_id;
        END IF;
    END IF;

    IF TG_OP = 'DELETE' OR (TG_OP = 'UPDATE' AND OLD.task_id IS NOT NULL) THEN
        UPDATE tasks SET
            likes_count = (SELECT COUNT(*) FROM votes WHERE task_id = OLD.task_id AND vote_type = 'like'),
            dislikes_count = (SELECT COUNT(*) FROM votes WHERE task_id = OLD.task_id AND vote_type = 'dislike')
        WHERE task_id = OLD.task_id;
    END IF;

    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_update_task_vote_counts
    AFTER INSERT OR DELETE OR UPDATE ON votes
    FOR EACH ROW
    WHEN (NEW.task_id IS NOT NULL OR OLD.task_id IS NOT NULL)
    EXECUTE FUNCTION update_task_vote_counts();


-- ---------------------------------------------------------------------
-- Block 7: Trigger — Comment Count for Tasks
-- Only counts approved Comments. Mirrors Contribution Pattern.
-- ---------------------------------------------------------------------
CREATE OR REPLACE FUNCTION update_task_comment_count()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
        IF NEW.task_id IS NOT NULL THEN
            UPDATE tasks
            SET comment_count = (
                SELECT COUNT(*) FROM comments
                WHERE task_id = NEW.task_id AND status = 'approved'
            )
            WHERE task_id = NEW.task_id;
        END IF;
    END IF;

    IF TG_OP = 'DELETE' OR (TG_OP = 'UPDATE' AND OLD.task_id IS NOT NULL) THEN
        UPDATE tasks
        SET comment_count = (
            SELECT COUNT(*) FROM comments
            WHERE task_id = OLD.task_id AND status = 'approved'
        )
        WHERE task_id = OLD.task_id;
    END IF;

    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_update_task_comment_count
    AFTER INSERT OR DELETE OR UPDATE OF status ON comments
    FOR EACH ROW
    WHEN (NEW.task_id IS NOT NULL OR OLD.task_id IS NOT NULL)
    EXECUTE FUNCTION update_task_comment_count();


-- ---------------------------------------------------------------------
-- Block 8: Views for QGIS (optional)
-- ---------------------------------------------------------------------
CREATE OR REPLACE VIEW tasks_points AS
    SELECT * FROM tasks WHERE geom_type = 'point';

CREATE OR REPLACE VIEW tasks_lines AS
    SELECT * FROM tasks WHERE geom_type = 'line';

CREATE OR REPLACE VIEW tasks_polygons AS
    SELECT * FROM tasks WHERE geom_type = 'polygon';