-- Dating App Database Schema
-- PostgreSQL 15+ Compatible
-- Run this script to create the database and all tables

-- ============================================================================
-- DATABASE CREATION
-- ============================================================================

-- Create the database user (if doesn't exist)
DO
$do$
BEGIN
  CREATE ROLE dating_app_user WITH LOGIN PASSWORD 'Aa123456';
EXCEPTION WHEN DUPLICATE_OBJECT THEN
  RAISE NOTICE 'Role dating_app_user already exists';
END
$do$;

-- Grant all privileges on database to dating_app_user
GRANT ALL PRIVILEGES ON DATABASE dating_app TO dating_app_user;

-- Grant all privileges on all tables in public schema to dating_app_user
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO dating_app_user;

-- Grant all privileges on all sequences in public schema to dating_app_user
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO dating_app_user;

-- Grant all privileges on schema itself
GRANT ALL PRIVILEGES ON SCHEMA public TO dating_app_user;

-- Set default privileges for future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO dating_app_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO dating_app_user;

-- ============================================================================
-- TABLE: USERS
-- ============================================================================
-- Stores user account information
CREATE TABLE IF NOT EXISTS users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(255) UNIQUE NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    hashed_password VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);

-- ============================================================================
-- TABLE: PROFILES
-- ============================================================================
-- Stores user profile information
CREATE TABLE IF NOT EXISTS profiles (
    id SERIAL PRIMARY KEY,
    user_id INTEGER NOT NULL UNIQUE,
    display_name VARCHAR(255) NOT NULL,
    age INTEGER NOT NULL,
    gender VARCHAR(50) NOT NULL,
    location VARCHAR(255) NOT NULL,
    bio TEXT,
    interests JSONB DEFAULT '[]',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_profiles_user_id ON profiles(user_id);

-- ============================================================================
-- TABLE: PHOTOS
-- ============================================================================
-- Stores user profile photos
CREATE TABLE IF NOT EXISTS photos (
    id SERIAL PRIMARY KEY,
    profile_id INTEGER NOT NULL,
    file_path VARCHAR(255) NOT NULL,
    display_order INTEGER NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_photos_profile_id ON photos(profile_id);

-- ============================================================================
-- TABLE: LIKES
-- ============================================================================
-- Tracks which users like which other users
CREATE TABLE IF NOT EXISTS likes (
    id SERIAL PRIMARY KEY,
    liker_id INTEGER NOT NULL,
    liked_id INTEGER NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(liker_id, liked_id),
    FOREIGN KEY (liker_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (liked_id) REFERENCES users(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_likes_liker_id ON likes(liker_id);
CREATE INDEX IF NOT EXISTS idx_likes_liked_id ON likes(liked_id);

-- ============================================================================
-- TABLE: CONVERSATIONS
-- ============================================================================
-- Stores 1:1 chat conversations between users
CREATE TABLE IF NOT EXISTS conversations (
    id SERIAL PRIMARY KEY,
    user_id_1 INTEGER NOT NULL,
    user_id_2 INTEGER NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(user_id_1, user_id_2),
    FOREIGN KEY (user_id_1) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id_2) REFERENCES users(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_conversations_users ON conversations(user_id_1, user_id_2);

-- ============================================================================
-- TABLE: MESSAGES
-- ============================================================================
-- Stores individual messages in conversations
CREATE TABLE IF NOT EXISTS messages (
    id SERIAL PRIMARY KEY,
    conversation_id INTEGER NOT NULL,
    sender_id INTEGER NOT NULL,
    content TEXT NOT NULL,
    read_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
    FOREIGN KEY (sender_id) REFERENCES users(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_messages_conversation_id ON messages(conversation_id);
CREATE INDEX IF NOT EXISTS idx_messages_created_at ON messages(created_at);

-- ============================================================================
-- SAMPLE DATA (Optional - Uncomment to insert test users)
-- ============================================================================

-- Test user 1: Alice (Password hash for 'password123')
INSERT INTO users (username, email, hashed_password) 
VALUES ('alice', 'alice@example.com', '$2b$12$u9bdKguk7ROP404cOx9FIuyKZoc3DK6el3y5muR8ayUnHG1bJewh2')
ON CONFLICT (email) DO NOTHING;

-- Test user 2: Bob
INSERT INTO users (username, email, hashed_password) 
VALUES ('bob', 'bob@example.com', '$2b$12$u9bdKguk7ROP404cOx9FIuyKZoc3DK6el3y5muR8ayUnHG1bJewh2')
ON CONFLICT (email) DO NOTHING;

-- Test user 3: Charlie
INSERT INTO users (username, email, hashed_password) 
VALUES ('charlie', 'charlie@example.com', '$2b$12$u9bdKguk7ROP404cOx9FIuyKZoc3DK6el3y5muR8ayUnHG1bJewh2')
ON CONFLICT (email) DO NOTHING;

-- Test user 4: Diana
INSERT INTO users (username, email, hashed_password) 
VALUES ('diana', 'diana@example.com', '$2b$12$u9bdKguk7ROP404cOx9FIuyKZoc3DK6el3y5muR8ayUnHG1bJewh2')
ON CONFLICT (email) DO NOTHING;

-- ============================================================================
-- SAMPLE PROFILES (Optional - Uncomment to create test profiles)
-- ============================================================================

-- Alice's profile
INSERT INTO profiles (user_id, display_name, age, gender, location, bio, interests)
VALUES (
    (SELECT id FROM users WHERE email = 'alice@example.com'),
    'Alice',
    28,
    'Female',
    'San Francisco, CA',
    'Love hiking and coffee. Looking for genuine connection.',
    '["hiking", "coffee", "reading", "travel"]'
)
ON CONFLICT (user_id) DO NOTHING;

-- Bob's profile
INSERT INTO profiles (user_id, display_name, age, gender, location, bio, interests)
VALUES (
    (SELECT id FROM users WHERE email = 'bob@example.com'),
    'Bob',
    30,
    'Male',
    'San Francisco, CA',
    'Software engineer who enjoys cooking and photography.',
    '["cooking", "photography", "gaming", "travel"]'
)
ON CONFLICT (user_id) DO NOTHING;

-- Charlie's profile
INSERT INTO profiles (user_id, display_name, age, gender, location, bio, interests)
VALUES (
    (SELECT id FROM users WHERE email = 'charlie@example.com'),
    'Charlie',
    27,
    'Male',
    'Los Angeles, CA',
    'Designer and musician. Love live music and good conversation.',
    '["music", "design", "art", "travel"]'
)
ON CONFLICT (user_id) DO NOTHING;

-- Diana's profile
INSERT INTO profiles (user_id, display_name, age, gender, location, bio, interests)
VALUES (
    (SELECT id FROM users WHERE email = 'diana@example.com'),
    'Diana',
    26,
    'Female',
    'Los Angeles, CA',
    'Yoga instructor and nature lover. Adventure seeker!',
    '["yoga", "hiking", "nature", "travel"]'
)
ON CONFLICT (user_id) DO NOTHING;

-- ============================================================================
-- VERIFICATION QUERIES
-- ============================================================================
-- Run these queries to verify everything was created correctly:
-- SELECT COUNT(*) as user_count FROM users;
-- SELECT COUNT(*) as profile_count FROM profiles;
-- SELECT COUNT(*) as photo_count FROM photos;
-- SELECT COUNT(*) as like_count FROM likes;
-- SELECT COUNT(*) as conversation_count FROM conversations;
-- SELECT COUNT(*) as message_count FROM messages;

-- ============================================================================
-- NOTES
-- ============================================================================
-- 
-- Password hashes used in sample data:
-- - Hash: $2b$12$u9bdKguk7ROP404cOx9FIuyKZoc3DK6el3y5muR8ayUnHG1bJewh2
-- - Password: 'password123'
--
-- To generate your own bcrypt hash, use Python:
-- from passlib.context import CryptContext
-- pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
-- hash = pwd_context.hash("your_password_here")
--
-- IMPORTANT BEFORE PRODUCTION:
-- 1. Change all password hashes to actual user passwords
-- 2. Update email addresses to real users
-- 3. Consider using proper user import/registration instead of direct inserts
-- 4. Remove sample data if not needed
--
-- DATABASE CONNECTION INFO:
-- Database: dating_app
-- Host: localhost (or your PostgreSQL host)
-- Port: 5432 (default)
-- User: postgres (or your database user)
-- Password: (set when installing PostgreSQL)
--
-- ============================================================================

-- ============================================================================
-- MIGRATIONS (Run these if tables already exist and need updates)
-- ============================================================================
-- Uncomment and run the following lines to update existing database:

-- Add username column to users table if it doesn't already exist:
-- ALTER TABLE users ADD COLUMN username VARCHAR(255) UNIQUE;

-- Add index on username for faster lookups:
-- CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);

-- Update dating_app_user permissions:
-- GRANT ALL PRIVILEGES ON DATABASE dating_app TO dating_app_user;
-- GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO dating_app_user;
-- GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO dating_app_user;
-- GRANT ALL PRIVILEGES ON SCHEMA public TO dating_app_user;
