-- Create shared_notes table for public sharing functionality
CREATE TABLE IF NOT EXISTS shared_notes (
    note_id TEXT PRIMARY KEY,
    user_id UUID NOT NULL,
    is_public BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    
    -- Foreign key constraint to notes table
    CONSTRAINT fk_shared_notes_note_id 
        FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE,
    
    -- Foreign key constraint to users table (auth.users)
    CONSTRAINT fk_shared_notes_user_id 
        FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE
);

-- Create index for performance on public notes
CREATE INDEX IF NOT EXISTS idx_shared_notes_is_public ON shared_notes(is_public);
CREATE INDEX IF NOT EXISTS idx_shared_notes_user_id ON shared_notes(user_id);

-- Enable Row Level Security
ALTER TABLE shared_notes ENABLE ROW LEVEL SECURITY;

-- Policy to allow users to view their own shared_notes entries
CREATE POLICY "Users can view their own shared notes" ON shared_notes
    FOR SELECT 
    TO authenticated
    USING (user_id = (SELECT auth.uid()));

-- Policy to allow anonymous users to view public notes
CREATE POLICY "Anyone can view public notes" ON shared_notes
    FOR SELECT 
    TO anon, authenticated
    USING (is_public = TRUE);

-- Policy to allow users to insert their own shared_notes entries
CREATE POLICY "Users can insert their own shared notes" ON shared_notes
    FOR INSERT 
    TO authenticated
    WITH CHECK (user_id = (SELECT auth.uid()));

-- Policy to allow users to update their own shared_notes entries
CREATE POLICY "Users can update their own shared notes" ON shared_notes
    FOR UPDATE 
    TO authenticated
    USING (user_id = (SELECT auth.uid()))
    WITH CHECK (user_id = (SELECT auth.uid()));

-- Policy to allow users to delete their own shared_notes entries
CREATE POLICY "Users can delete their own shared notes" ON shared_notes
    FOR DELETE 
    TO authenticated
    USING (user_id = (SELECT auth.uid()));

-- Create note_access table for tablo-based sharing
CREATE TABLE IF NOT EXISTS note_access (
    id SERIAL PRIMARY KEY,
    note_id TEXT NOT NULL,
    user_id UUID NOT NULL,
    tablo_id TEXT,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    
    -- Foreign key constraint to notes table
    CONSTRAINT fk_note_access_note_id 
        FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE,
    
    -- Foreign key constraint to users table (auth.users)
    CONSTRAINT fk_note_access_user_id 
        FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE,
    
    -- Foreign key constraint to tablos table (nullable for "all tablos" sharing)
    CONSTRAINT fk_note_access_tablo_id 
        FOREIGN KEY (tablo_id) REFERENCES tablos(id) ON DELETE CASCADE
);

-- Create indexes for performance
CREATE INDEX IF NOT EXISTS idx_note_access_note_id ON note_access(note_id);
CREATE INDEX IF NOT EXISTS idx_note_access_user_id ON note_access(user_id);
CREATE INDEX IF NOT EXISTS idx_note_access_tablo_id ON note_access(tablo_id);
CREATE INDEX IF NOT EXISTS idx_note_access_is_active ON note_access(is_active);

-- Unique constraint for specific tablo sharing (when tablo_id IS NOT NULL)
CREATE UNIQUE INDEX IF NOT EXISTS unique_note_access_with_tablo 
    ON note_access(note_id, user_id, tablo_id) 
    WHERE tablo_id IS NOT NULL;

-- Unique constraint for "all tablos" sharing (when tablo_id IS NULL)
-- Only one NULL tablo_id per (note_id, user_id) combination
CREATE UNIQUE INDEX IF NOT EXISTS unique_note_access_all_tablos 
    ON note_access(note_id, user_id) 
    WHERE tablo_id IS NULL;

-- Enable Row Level Security
ALTER TABLE note_access ENABLE ROW LEVEL SECURITY;

-- Policy to allow users to view their own note_access entries
CREATE POLICY "Users can view their own note access" ON note_access
    FOR SELECT 
    TO authenticated
    USING (user_id = (SELECT auth.uid()));

-- Policy to allow users to view notes shared with their tablos
CREATE POLICY "Users can view notes shared with their tablos" ON note_access
    FOR SELECT 
    TO authenticated
    USING (
        is_active = TRUE
        AND (
            -- Shared with all tablos (tablo_id is NULL)
            tablo_id IS NULL
            -- Or shared with a specific tablo where the user has access
            OR EXISTS (
                SELECT 1 FROM tablo_access
                WHERE tablo_access.tablo_id = note_access.tablo_id
                AND tablo_access.user_id = (SELECT auth.uid())
                AND tablo_access.is_active = TRUE
            )
        )
    );

-- Policy to allow users to insert their own note_access entries
CREATE POLICY "Users can insert their own note access" ON note_access
    FOR INSERT 
    TO authenticated
    WITH CHECK (user_id = (SELECT auth.uid()));

-- Policy to allow users to update their own note_access entries
CREATE POLICY "Users can update their own note access" ON note_access
    FOR UPDATE 
    TO authenticated
    USING (user_id = (SELECT auth.uid()))
    WITH CHECK (user_id = (SELECT auth.uid()));

-- Policy to allow users to delete their own note_access entries
CREATE POLICY "Users can delete their own note access" ON note_access
    FOR DELETE 
    TO authenticated
    USING (user_id = (SELECT auth.uid()));

-- Add comments to document the tables
COMMENT ON TABLE shared_notes IS 
    'Tracks which notes are shared publicly with Row Level Security';

COMMENT ON COLUMN shared_notes.note_id IS 
    'Foreign key reference to notes.id';

COMMENT ON COLUMN shared_notes.user_id IS 
    'Foreign key reference to auth.users.id - owner of the note';

COMMENT ON COLUMN shared_notes.is_public IS 
    'When TRUE, the note is publicly accessible via /notes/public/:noteId';

COMMENT ON TABLE note_access IS 
    'Tracks which notes are shared with tablos. When tablo_id IS NULL and is_active = TRUE, the note is shared with all user tablos. Uses partial unique indexes to handle NULL values correctly.';

COMMENT ON COLUMN note_access.tablo_id IS 
    'Foreign key reference to tablos.id - NULL means shared with all user tablos. Partial unique indexes ensure only one NULL per (note_id, user_id) combination.';

COMMENT ON COLUMN note_access.is_active IS 
    'When TRUE, the sharing is active';

