-- Employee Workstation Activity Tracking System
-- Database Schema Creation Script

-- Instructions:
-- 1. For SQLite: sqlite3 work_events.db < create_db.sql
-- 2. For PostgreSQL: psql -U username -d database_name -f create_db.sql

-- Drop existing table if it exists
DROP TABLE IF EXISTS work_events;

-- Create the work_events table
CREATE TABLE work_events (
    id SERIAL PRIMARY KEY,
    "user" VARCHAR(100) NOT NULL,  -- Note the double quotes
    state VARCHAR(10) NOT NULL CHECK (state IN ('working', 'stopped')),
    ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Create indexes for performance optimization
CREATE INDEX idx_work_events_user ON work_events("user");
CREATE INDEX idx_work_events_ts ON work_events(ts);
CREATE INDEX idx_work_events_user_state ON work_events("user", state);

-- Optional: Sample data for testing (comment out in production)

-- Clear previous sample data if necessary before inserting new data
-- DELETE FROM work_events WHERE "user" LIKE 'User %' OR "user" LIKE 'user%';

-- Remove older generic sample data
/*
INSERT INTO work_events ("user", state, ts) VALUES
    ('user1', 'working', CURRENT_TIMESTAMP - INTERVAL '2 hours'),
    ('user1', 'stopped', CURRENT_TIMESTAMP - INTERVAL '1 hour'),
    ('user1', 'working', CURRENT_TIMESTAMP - INTERVAL '30 minutes'),
    ('user2', 'working', CURRENT_TIMESTAMP - INTERVAL '3 hours'),
    ('user2', 'stopped', CURRENT_TIMESTAMP - INTERVAL '2 hours 30 minutes'),
    ('user2', 'working', CURRENT_TIMESTAMP - INTERVAL '2 hours'),
    ('user2', 'stopped', CURRENT_TIMESTAMP - INTERVAL '1 hour');
*/

-- Example queries for reporting

-- 1. Daily activity summary per user

SELECT 
    "user",
    DATE(ts) AS day,
    COUNT(*) AS event_count,
    SUM(CASE WHEN state = 'working' THEN 1 ELSE 0 END) AS working_events
FROM work_events
GROUP BY "user", day
ORDER BY day DESC, "user";


-- 2. Weekly activity summary

SELECT 
    "user",
    date_trunc('week', ts) AS week_start,
    COUNT(*) AS event_count
FROM work_events
GROUP BY "user", week_start
ORDER BY week_start DESC, "user";


-- 3. Monthly activity summary

SELECT 
    "user",
    date_trunc('month', ts) AS month_start,
    COUNT(*) AS event_count
FROM work_events
GROUP BY "user", month_start
ORDER BY month_start DESC, "user";


-- Notes on data retention:
-- According to requirements, raw event logs should be retained for 1 year.
-- Setup a periodic cleanup job to remove old data:

-- PostgreSQL:

DELETE FROM work_events 
WHERE ts < CURRENT_TIMESTAMP - INTERVAL '1 year';


-- SQLite:
/*
DELETE FROM work_events 
WHERE ts < datetime('now', '-1 year');
*/ 

-- Enhanced Sample Data Generation (Relative to assumed date 2025-05-04)
-- Ensures Users A-E have data for Today, This Week, and This Month (April)



-- Sample data for real users: Robert, Ilia, and Nika
-- Robert: Working pattern for today, this week, and this month
INSERT INTO work_events ("user", state, ts) VALUES ('Robert', 'working', '2025-05-04 08:30:00'); -- Today
INSERT INTO work_events ("user", state, ts) VALUES ('Robert', 'stopped', '2025-05-04 12:30:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Robert', 'working', '2025-05-04 13:15:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Robert', 'stopped', '2025-05-04 17:00:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Robert', 'working', '2025-05-02 08:45:00'); -- This Week
INSERT INTO work_events ("user", state, ts) VALUES ('Robert', 'stopped', '2025-05-02 16:15:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Robert', 'working', '2025-04-15 09:00:00'); -- This Month
INSERT INTO work_events ("user", state, ts) VALUES ('Robert', 'stopped', '2025-04-15 17:30:00');

-- Ilia: Working pattern for today, this week, and this month
INSERT INTO work_events ("user", state, ts) VALUES ('Ilia', 'working', '2025-05-04 09:00:00'); -- Today
INSERT INTO work_events ("user", state, ts) VALUES ('Ilia', 'stopped', '2025-05-04 13:00:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Ilia', 'working', '2025-05-04 14:00:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Ilia', 'stopped', '2025-05-04 18:00:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Ilia', 'working', '2025-05-03 09:30:00'); -- This Week
INSERT INTO work_events ("user", state, ts) VALUES ('Ilia', 'stopped', '2025-05-03 17:30:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Ilia', 'working', '2025-04-20 08:30:00'); -- This Month
INSERT INTO work_events ("user", state, ts) VALUES ('Ilia', 'stopped', '2025-04-20 16:30:00');

-- Nika: Working pattern for today, this week, and this month
INSERT INTO work_events ("user", state, ts) VALUES ('Nika', 'working', '2025-05-04 08:15:00'); -- Today
INSERT INTO work_events ("user", state, ts) VALUES ('Nika', 'stopped', '2025-05-04 12:00:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Nika', 'working', '2025-05-04 12:45:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Nika', 'stopped', '2025-05-04 16:30:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Nika', 'working', '2025-05-01 08:30:00'); -- This Week
INSERT INTO work_events ("user", state, ts) VALUES ('Nika', 'stopped', '2025-05-01 16:45:00');
INSERT INTO work_events ("user", state, ts) VALUES ('Nika', 'working', '2025-04-10 09:15:00'); -- This Month
INSERT INTO work_events ("user", state, ts) VALUES ('Nika', 'stopped', '2025-04-10 17:15:00');

-- Enhanced SQL queries for reporting with duration calculations

-- 4. Daily working duration per user (for dashboard)
-- This calculates the total working hours per day by matching working->stopped pairs
SELECT 
    w1."user",
    DATE(w1.ts) AS day,
    SUM(
        EXTRACT(EPOCH FROM (w2.ts - w1.ts))/3600
    ) AS duration_hours,
    MIN(CASE WHEN w1.state = 'working' THEN w1.ts END) AS first_login_time
FROM 
    work_events w1
JOIN 
    work_events w2 ON w1."user" = w2."user" 
    AND w1.state = 'working' 
    AND w2.state = 'stopped'
    AND w2.ts > w1.ts
    AND NOT EXISTS (
        SELECT 1 FROM work_events w3
        WHERE w3."user" = w1."user"
        AND w3.ts > w1.ts AND w3.ts < w2.ts
    )
GROUP BY 
    w1."user", day
ORDER BY 
    day DESC, w1."user";

-- 5. Weekly working duration per user (for dashboard)
SELECT 
    w1."user",
    date_trunc('week', w1.ts) AS week_start,
    SUM(
        EXTRACT(EPOCH FROM (w2.ts - w1.ts))/3600
    ) AS duration_hours,
    MIN(CASE WHEN w1.state = 'working' THEN w1.ts END) AS first_login_time
FROM 
    work_events w1
JOIN 
    work_events w2 ON w1."user" = w2."user" 
    AND w1.state = 'working' 
    AND w2.state = 'stopped'
    AND w2.ts > w1.ts
    AND NOT EXISTS (
        SELECT 1 FROM work_events w3
        WHERE w3."user" = w1."user"
        AND w3.ts > w1.ts AND w3.ts < w2.ts
    )
GROUP BY 
    w1."user", week_start
ORDER BY 
    week_start DESC, w1."user";

-- 6. Monthly working duration per user (for dashboard)
SELECT 
    w1."user",
    date_trunc('month', w1.ts) AS month_start,
    SUM(
        EXTRACT(EPOCH FROM (w2.ts - w1.ts))/3600
    ) AS duration_hours,
    MIN(CASE WHEN w1.state = 'working' THEN w1.ts END) AS first_login_time
FROM 
    work_events w1
JOIN 
    work_events w2 ON w1."user" = w2."user" 
    AND w1.state = 'working' 
    AND w2.state = 'stopped'
    AND w2.ts > w1.ts
    AND NOT EXISTS (
        SELECT 1 FROM work_events w3
        WHERE w3."user" = w1."user"
        AND w3.ts > w1.ts AND w3.ts < w2.ts
    )
GROUP BY 
    w1."user", month_start
ORDER BY 
    month_start DESC, w1."user";

-- 7. Detailed user activity log for specific user and date range
-- This query shows all work sessions with start, end times and duration
-- Use :username and :start_date, :end_date as parameters
SELECT 
    w1."user",
    DATE(w1.ts) AS work_date,
    w1.ts AS start_time,
    w2.ts AS end_time,
    EXTRACT(EPOCH FROM (w2.ts - w1.ts))/3600 AS session_duration_hours
FROM 
    work_events w1
JOIN 
    work_events w2 ON w1."user" = w2."user" 
    AND w1.state = 'working' 
    AND w2.state = 'stopped'
    AND w2.ts > w1.ts
    AND NOT EXISTS (
        SELECT 1 FROM work_events w3
        WHERE w3."user" = w1."user"
        AND w3.ts > w1.ts AND w3.ts < w2.ts
    )
WHERE 
    w1."user" = :username
    AND DATE(w1.ts) BETWEEN :start_date AND :end_date
ORDER BY 
    w1.ts;

-- 8. Filter for specific time periods (Today, This Week, This Month)
-- Today's work duration by user
SELECT 
    w1."user",
    CURRENT_DATE AS day,
    SUM(
        EXTRACT(EPOCH FROM (w2.ts - w1.ts))/3600
    ) AS duration_hours,
    MIN(CASE WHEN w1.state = 'working' THEN w1.ts END) AS first_login_time
FROM 
    work_events w1
JOIN 
    work_events w2 ON w1."user" = w2."user" 
    AND w1.state = 'working' 
    AND w2.state = 'stopped'
    AND w2.ts > w1.ts
    AND NOT EXISTS (
        SELECT 1 FROM work_events w3
        WHERE w3."user" = w1."user"
        AND w3.ts > w1.ts AND w3.ts < w2.ts
    )
WHERE 
    DATE(w1.ts) = CURRENT_DATE
GROUP BY 
    w1."user"
ORDER BY 
    w1."user";

-- This Week's work duration by user
SELECT 
    w1."user",
    date_trunc('week', CURRENT_DATE) AS week_start,
    SUM(
        EXTRACT(EPOCH FROM (w2.ts - w1.ts))/3600
    ) AS duration_hours,
    MIN(CASE WHEN w1.state = 'working' THEN w1.ts END) AS first_login_time
FROM 
    work_events w1
JOIN 
    work_events w2 ON w1."user" = w2."user" 
    AND w1.state = 'working' 
    AND w2.state = 'stopped'
    AND w2.ts > w1.ts
    AND NOT EXISTS (
        SELECT 1 FROM work_events w3
        WHERE w3."user" = w1."user"
        AND w3.ts > w1.ts AND w3.ts < w2.ts
    )
WHERE 
    date_trunc('week', w1.ts) = date_trunc('week', CURRENT_DATE)
GROUP BY 
    w1."user"
ORDER BY 
    w1."user";

-- This Month's work duration by user
SELECT 
    w1."user",
    date_trunc('month', CURRENT_DATE) AS month_start,
    SUM(
        EXTRACT(EPOCH FROM (w2.ts - w1.ts))/3600
    ) AS duration_hours,
    MIN(CASE WHEN w1.state = 'working' THEN w1.ts END) AS first_login_time
FROM 
    work_events w1
JOIN 
    work_events w2 ON w1."user" = w2."user" 
    AND w1.state = 'working' 
    AND w2.state = 'stopped'
    AND w2.ts > w1.ts
    AND NOT EXISTS (
        SELECT 1 FROM work_events w3
        WHERE w3."user" = w1."user"
        AND w3.ts > w1.ts AND w3.ts < w2.ts
    )
WHERE 
    date_trunc('month', w1.ts) = date_trunc('month', CURRENT_DATE)
GROUP BY 
    w1."user"
ORDER BY 
    w1."user"; 