-- Migration: 014_user_analytics.sql
-- Description: User activity tracking and analytics
-- Created: 2026-01-13
-- Author: Claude

-- ============================================================
-- TABELE ANALITYKI UŻYTKOWNIKÓW
-- ============================================================

-- Sesje użytkowników
CREATE TABLE IF NOT EXISTS user_sessions (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
    session_id VARCHAR(100) UNIQUE NOT NULL,

    -- Czas sesji
    started_at TIMESTAMP NOT NULL DEFAULT NOW(),
    ended_at TIMESTAMP,
    last_activity_at TIMESTAMP NOT NULL DEFAULT NOW(),
    duration_seconds INTEGER,

    -- Urządzenie
    ip_address VARCHAR(45),
    user_agent TEXT,
    device_type VARCHAR(20),      -- desktop, mobile, tablet
    browser VARCHAR(50),
    browser_version VARCHAR(20),
    os VARCHAR(50),
    os_version VARCHAR(20),

    -- Lokalizacja (z IP)
    country VARCHAR(100),
    city VARCHAR(100),
    region VARCHAR(100),

    -- Metryki sesji
    page_views_count INTEGER DEFAULT 0,
    clicks_count INTEGER DEFAULT 0,

    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_user_sessions_user ON user_sessions(user_id);
CREATE INDEX IF NOT EXISTS idx_user_sessions_started ON user_sessions(started_at);
CREATE INDEX IF NOT EXISTS idx_user_sessions_session_id ON user_sessions(session_id);

-- Wyświetlenia stron
CREATE TABLE IF NOT EXISTS page_views (
    id SERIAL PRIMARY KEY,
    session_id INTEGER REFERENCES user_sessions(id) ON DELETE CASCADE,
    user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,

    -- Strona
    url VARCHAR(2000) NOT NULL,
    path VARCHAR(500) NOT NULL,
    page_title VARCHAR(500),
    referrer VARCHAR(2000),

    -- Czas
    viewed_at TIMESTAMP NOT NULL DEFAULT NOW(),
    time_on_page_seconds INTEGER,

    -- Kontekst
    company_id INTEGER REFERENCES companies(id) ON DELETE SET NULL,

    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_page_views_session ON page_views(session_id);
CREATE INDEX IF NOT EXISTS idx_page_views_user ON page_views(user_id);
CREATE INDEX IF NOT EXISTS idx_page_views_path ON page_views(path);
CREATE INDEX IF NOT EXISTS idx_page_views_viewed ON page_views(viewed_at);
CREATE INDEX IF NOT EXISTS idx_page_views_company ON page_views(company_id);

-- Kliknięcia użytkowników
CREATE TABLE IF NOT EXISTS user_clicks (
    id SERIAL PRIMARY KEY,
    session_id INTEGER REFERENCES user_sessions(id) ON DELETE CASCADE,
    page_view_id INTEGER REFERENCES page_views(id) ON DELETE CASCADE,
    user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,

    -- Element kliknięty
    element_type VARCHAR(50),     -- button, link, card, nav, form
    element_id VARCHAR(100),
    element_text VARCHAR(255),
    element_class VARCHAR(500),
    target_url VARCHAR(2000),

    -- Pozycja
    x_position INTEGER,
    y_position INTEGER,

    clicked_at TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_user_clicks_session ON user_clicks(session_id);
CREATE INDEX IF NOT EXISTS idx_user_clicks_element ON user_clicks(element_type);
CREATE INDEX IF NOT EXISTS idx_user_clicks_clicked ON user_clicks(clicked_at);

-- Dzienne statystyki (agregowane)
CREATE TABLE IF NOT EXISTS analytics_daily (
    id SERIAL PRIMARY KEY,
    date DATE UNIQUE NOT NULL,

    -- Sesje
    total_sessions INTEGER DEFAULT 0,
    unique_users INTEGER DEFAULT 0,
    new_users INTEGER DEFAULT 0,
    returning_users INTEGER DEFAULT 0,
    anonymous_sessions INTEGER DEFAULT 0,

    -- Aktywność
    total_page_views INTEGER DEFAULT 0,
    total_clicks INTEGER DEFAULT 0,
    avg_session_duration_seconds INTEGER,
    avg_pages_per_session NUMERIC(5,2),

    -- Urządzenia
    desktop_sessions INTEGER DEFAULT 0,
    mobile_sessions INTEGER DEFAULT 0,
    tablet_sessions INTEGER DEFAULT 0,

    -- Engagement
    bounce_rate NUMERIC(5,2),     -- % sesji z 1 page view

    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_analytics_daily_date ON analytics_daily(date);

-- Popularne strony (dzienne)
CREATE TABLE IF NOT EXISTS popular_pages_daily (
    id SERIAL PRIMARY KEY,
    date DATE NOT NULL,
    path VARCHAR(500) NOT NULL,
    page_title VARCHAR(500),

    views_count INTEGER DEFAULT 0,
    unique_visitors INTEGER DEFAULT 0,
    avg_time_seconds INTEGER,

    UNIQUE(date, path)
);

CREATE INDEX IF NOT EXISTS idx_popular_pages_date ON popular_pages_daily(date);

-- ============================================================
-- GRANT PERMISSIONS
-- ============================================================
GRANT ALL ON TABLE user_sessions TO nordabiz_app;
GRANT ALL ON TABLE page_views TO nordabiz_app;
GRANT ALL ON TABLE user_clicks TO nordabiz_app;
GRANT ALL ON TABLE analytics_daily TO nordabiz_app;
GRANT ALL ON TABLE popular_pages_daily TO nordabiz_app;

GRANT USAGE, SELECT ON SEQUENCE user_sessions_id_seq TO nordabiz_app;
GRANT USAGE, SELECT ON SEQUENCE page_views_id_seq TO nordabiz_app;
GRANT USAGE, SELECT ON SEQUENCE user_clicks_id_seq TO nordabiz_app;
GRANT USAGE, SELECT ON SEQUENCE analytics_daily_id_seq TO nordabiz_app;
GRANT USAGE, SELECT ON SEQUENCE popular_pages_daily_id_seq TO nordabiz_app;

-- ============================================================
-- TRIGGER: Update analytics_daily on new session/page_view
-- ============================================================

-- Function to update daily analytics
CREATE OR REPLACE FUNCTION update_analytics_daily()
RETURNS TRIGGER AS $$
DECLARE
    target_date DATE;
BEGIN
    IF TG_TABLE_NAME = 'user_sessions' THEN
        target_date := DATE(NEW.started_at);
    ELSIF TG_TABLE_NAME = 'page_views' THEN
        target_date := DATE(NEW.viewed_at);
    ELSE
        RETURN NEW;
    END IF;

    -- Insert or update daily stats
    INSERT INTO analytics_daily (date, total_sessions, total_page_views, updated_at)
    VALUES (target_date, 0, 0, NOW())
    ON CONFLICT (date) DO NOTHING;

    -- Update counts based on trigger source
    IF TG_TABLE_NAME = 'user_sessions' THEN
        UPDATE analytics_daily SET
            total_sessions = total_sessions + 1,
            unique_users = (
                SELECT COUNT(DISTINCT user_id)
                FROM user_sessions
                WHERE DATE(started_at) = target_date AND user_id IS NOT NULL
            ),
            anonymous_sessions = (
                SELECT COUNT(*)
                FROM user_sessions
                WHERE DATE(started_at) = target_date AND user_id IS NULL
            ),
            desktop_sessions = (
                SELECT COUNT(*) FROM user_sessions
                WHERE DATE(started_at) = target_date AND device_type = 'desktop'
            ),
            mobile_sessions = (
                SELECT COUNT(*) FROM user_sessions
                WHERE DATE(started_at) = target_date AND device_type = 'mobile'
            ),
            tablet_sessions = (
                SELECT COUNT(*) FROM user_sessions
                WHERE DATE(started_at) = target_date AND device_type = 'tablet'
            ),
            updated_at = NOW()
        WHERE date = target_date;

    ELSIF TG_TABLE_NAME = 'page_views' THEN
        UPDATE analytics_daily SET
            total_page_views = total_page_views + 1,
            updated_at = NOW()
        WHERE date = target_date;
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Create triggers
DROP TRIGGER IF EXISTS trg_update_analytics_on_session ON user_sessions;
CREATE TRIGGER trg_update_analytics_on_session
    AFTER INSERT ON user_sessions
    FOR EACH ROW
    EXECUTE FUNCTION update_analytics_daily();

DROP TRIGGER IF EXISTS trg_update_analytics_on_pageview ON page_views;
CREATE TRIGGER trg_update_analytics_on_pageview
    AFTER INSERT ON page_views
    FOR EACH ROW
    EXECUTE FUNCTION update_analytics_daily();

-- ============================================================
-- COMMENTS
-- ============================================================
COMMENT ON TABLE user_sessions IS 'Sesje użytkowników portalu NordaBiznes';
COMMENT ON TABLE page_views IS 'Wyświetlenia stron przez użytkowników';
COMMENT ON TABLE user_clicks IS 'Kliknięcia elementów na stronach';
COMMENT ON TABLE analytics_daily IS 'Dzienne statystyki agregowane';
COMMENT ON TABLE popular_pages_daily IS 'Popularne strony - dzienne agregaty';

COMMENT ON COLUMN user_sessions.device_type IS 'Typ urządzenia: desktop, mobile, tablet';
COMMENT ON COLUMN user_sessions.duration_seconds IS 'Czas trwania sesji w sekundach';
COMMENT ON COLUMN page_views.time_on_page_seconds IS 'Czas spędzony na stronie w sekundach';
COMMENT ON COLUMN analytics_daily.bounce_rate IS 'Procent sesji z tylko 1 wyświetleniem strony';
