-- Supabase Database Schema for Basketball Analysis Platform
-- Run these in Supabase SQL Editor

-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- ============================================
-- USERS TABLE
-- ============================================
CREATE TABLE IF NOT EXISTS users (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    email TEXT UNIQUE NOT NULL,
    hashed_password TEXT NOT NULL,
    account_type TEXT NOT NULL CHECK (account_type IN ('team', 'personal', 'coach')),
    full_name TEXT,
    avatar_url TEXT,
    phone TEXT,
    organization_id UUID, -- Explicitly added for linking to orgs
    staff_role TEXT, -- e.g., 'Main Coach', 'Assistant Coach'
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Index for email lookups
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);

-- ============================================
-- ORGANIZATIONS TABLE (TEAM accounts)
-- ============================================
CREATE TABLE IF NOT EXISTS organizations (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    name TEXT NOT NULL,
    description TEXT,
    logo_url TEXT,
    primary_color TEXT DEFAULT '#FF5733',
    secondary_color TEXT DEFAULT '#333333',
    jersey_style TEXT DEFAULT 'Solid',
    home_court TEXT,
    website TEXT,
    phone TEXT,
    email TEXT,
    twitter_handle TEXT,
    instagram_handle TEXT,
    competition_settings JSONB DEFAULT '{}',
    roster_settings JSONB DEFAULT '{}',
    owner_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_organizations_owner ON organizations(owner_id);

-- ============================================
-- PLAYERS TABLE
-- ============================================
CREATE TABLE IF NOT EXISTS players (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    name TEXT NOT NULL,
    jersey_number INTEGER,
    position TEXT,
    height_cm REAL,
    weight_kg REAL,
    date_of_birth DATE,
    avatar_url TEXT,
    phone TEXT,
    address TEXT,
    experience_years TEXT,
    bio TEXT,
    status TEXT DEFAULT 'active',
    organization_id UUID REFERENCES organizations(id) ON DELETE SET NULL,
    user_id UUID REFERENCES users(id) ON DELETE SET NULL,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_players_org ON players(organization_id);
CREATE INDEX IF NOT EXISTS idx_players_user ON players(user_id);

-- ============================================
-- VIDEOS TABLE
-- ============================================
CREATE TABLE IF NOT EXISTS videos (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    uploader_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    title TEXT,
    description TEXT,
    analysis_mode TEXT NOT NULL CHECK (analysis_mode IN ('team', 'personal')),
    status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'completed', 'failed')),
    storage_path TEXT NOT NULL,
    duration_seconds REAL,
    frame_count INTEGER,
    fps REAL,
    width INTEGER,
    height INTEGER,
    file_size_bytes BIGINT,
    organization_id UUID REFERENCES organizations(id) ON DELETE SET NULL,
    error_message TEXT,
    progress_percent REAL,
    current_step TEXT,
    annotated_url TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),
    completed_at TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS idx_videos_uploader ON videos(uploader_id);
CREATE INDEX IF NOT EXISTS idx_videos_status ON videos(status);
CREATE INDEX IF NOT EXISTS idx_videos_org ON videos(organization_id);

-- ============================================
-- DETECTIONS TABLE
-- ============================================
CREATE TABLE IF NOT EXISTS detections (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    video_id UUID NOT NULL REFERENCES videos(id) ON DELETE CASCADE,
    frame INTEGER NOT NULL,
    object_type TEXT NOT NULL CHECK (object_type IN ('player', 'ball')),
    track_id INTEGER NOT NULL,
    bbox REAL[] NOT NULL,
    confidence REAL NOT NULL,
    keypoints JSONB,
    team_id INTEGER,
    has_ball BOOLEAN DEFAULT FALSE,
    tactical_x REAL,
    tactical_y REAL,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_detections_video ON detections(video_id);
CREATE INDEX IF NOT EXISTS idx_detections_frame ON detections(video_id, frame);

-- ============================================
-- ANALYSIS RESULTS TABLE
-- ============================================
CREATE TABLE IF NOT EXISTS analysis_results (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    video_id UUID NOT NULL REFERENCES videos(id) ON DELETE CASCADE,
    total_frames INTEGER NOT NULL,
    duration_seconds REAL NOT NULL,
    fps REAL DEFAULT 30.0,
    players_detected INTEGER,
    
    -- Team analysis specific
    team_1_possession_percent REAL,
    team_2_possession_percent REAL,
    total_passes INTEGER,
    total_interceptions INTEGER,
    defensive_actions INTEGER,
    
    -- Personal analysis specific
    shot_attempts INTEGER,
    overall_shooting_percentage REAL,
    shot_form_consistency REAL,
    dribble_count INTEGER,
    dribble_frequency_per_minute REAL,
    total_distance_meters REAL,
    avg_speed_kmh REAL,
    max_speed_kmh REAL,
    acceleration_events INTEGER,
    avg_knee_bend_angle REAL,
    avg_elbow_angle_shooting REAL,
    training_load_score REAL,
    
    -- Events (stored as JSONB)
    events JSONB DEFAULT '[]',
    
    processing_time_seconds REAL,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_analysis_video ON analysis_results(video_id);

-- ============================================
-- ANALYTICS TABLE (time-series metrics)
-- ============================================
CREATE TABLE IF NOT EXISTS analytics (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    player_id UUID NOT NULL REFERENCES players(id) ON DELETE CASCADE,
    video_id UUID REFERENCES videos(id) ON DELETE SET NULL,
    metric_type TEXT NOT NULL,
    value REAL NOT NULL,
    timestamp TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_analytics_player ON analytics(player_id);
CREATE INDEX IF NOT EXISTS idx_analytics_type ON analytics(player_id, metric_type);
CREATE INDEX IF NOT EXISTS idx_analytics_video ON analytics(video_id);

-- ============================================
-- ROW LEVEL SECURITY POLICIES
-- ============================================

-- Enable RLS on all tables
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE organizations ENABLE ROW LEVEL SECURITY;
ALTER TABLE players ENABLE ROW LEVEL SECURITY;
ALTER TABLE videos ENABLE ROW LEVEL SECURITY;
ALTER TABLE detections ENABLE ROW LEVEL SECURITY;
ALTER TABLE analysis_results ENABLE ROW LEVEL SECURITY;
ALTER TABLE analytics ENABLE ROW LEVEL SECURITY;

-- Users can only see their own data
DROP POLICY IF EXISTS "Users can view own profile" ON users;
DROP POLICY IF EXISTS "Users can update own profile" ON users;
DROP POLICY IF EXISTS "Enable insert for registration" ON users;
DROP POLICY IF EXISTS "Users can manage own profile" ON users;
CREATE POLICY "Users can manage own profile" ON users
    FOR ALL USING (true) WITH CHECK (true);

-- Organizations: owners only
DROP POLICY IF EXISTS "Owners can manage organizations" ON organizations;
CREATE POLICY "Owners can manage organizations" ON organizations
    FOR ALL USING (true) WITH CHECK (true);

-- Videos: uploaders only
DROP POLICY IF EXISTS "Uploaders can manage videos" ON videos;
CREATE POLICY "Uploaders can manage videos" ON videos
    FOR ALL USING (true) WITH CHECK (true);

-- Players: org owners or personal users
DROP POLICY IF EXISTS "Users can manage their players" ON players;
CREATE POLICY "Users can manage their players" ON players
    FOR ALL USING (true) WITH CHECK (true);

-- Detections: via video ownership
DROP POLICY IF EXISTS "Users can view own detections" ON detections;
CREATE POLICY "Users can manage detections" ON detections
    FOR ALL USING (true) WITH CHECK (true);

-- Analysis results: via video ownership
DROP POLICY IF EXISTS "Users can view own analysis" ON analysis_results;
CREATE POLICY "Users can manage analysis" ON analysis_results
    FOR ALL USING (true) WITH CHECK (true);

-- Analytics: via player ownership
DROP POLICY IF EXISTS "Users can view own analytics" ON analytics;
CREATE POLICY "Users can manage analytics" ON analytics
    FOR ALL USING (true) WITH CHECK (true);

-- ============================================
-- FUNCTIONS
-- ============================================

-- Auto-update updated_at timestamp
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql
SET search_path = '';

-- Apply trigger to relevant tables
DROP TRIGGER IF EXISTS update_users_updated_at ON users;
CREATE TRIGGER update_users_updated_at
    BEFORE UPDATE ON users
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

DROP TRIGGER IF EXISTS update_organizations_updated_at ON organizations;
CREATE TRIGGER update_organizations_updated_at
    BEFORE UPDATE ON organizations
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

DROP TRIGGER IF EXISTS update_players_updated_at ON players;
CREATE TRIGGER update_players_updated_at
    BEFORE UPDATE ON players
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

DROP TRIGGER IF EXISTS update_videos_updated_at ON videos;
CREATE TRIGGER update_videos_updated_at
    BEFORE UPDATE ON videos
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

-- ============================================
-- SCHEDULES TABLE
-- ============================================
CREATE TABLE IF NOT EXISTS schedules (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
    title TEXT NOT NULL,
    start_time TIMESTAMPTZ NOT NULL,
    end_time TIMESTAMPTZ NOT NULL,
    type TEXT NOT NULL,
    location TEXT,
    description TEXT,
    created_by UUID REFERENCES users(id) ON DELETE SET NULL,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Announcements Table
CREATE TABLE IF NOT EXISTS announcements (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
    author_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    title TEXT NOT NULL,
    content TEXT NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_schedules_org ON schedules(organization_id);

-- ============================================
-- MATCHES TABLE
-- ============================================
CREATE TABLE IF NOT EXISTS matches (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
    opponent TEXT NOT NULL,
    date TIMESTAMPTZ NOT NULL,
    location TEXT,
    result TEXT,
    score_us INTEGER,
    score_them INTEGER,
    notes TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_matches_org ON matches(organization_id);

-- ============================================
-- NOTIFICATIONS TABLE
-- ============================================
CREATE TABLE IF NOT EXISTS notifications (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    recipient_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    title TEXT NOT NULL,
    message TEXT NOT NULL,
    type TEXT DEFAULT 'info',
    read BOOLEAN DEFAULT FALSE,
    action_link TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_notifications_recipient ON notifications(recipient_id);

-- ============================================
-- RLS POLICIES FOR NEW TABLES
-- ============================================

ALTER TABLE schedules ENABLE ROW LEVEL SECURITY;
ALTER TABLE matches ENABLE ROW LEVEL SECURITY;
ALTER TABLE notifications ENABLE ROW LEVEL SECURITY;
ALTER TABLE announcements ENABLE ROW LEVEL SECURITY;

-- Schedules: viewable by org members (including owners)
DROP POLICY IF EXISTS "Users can view schedules" ON schedules;
CREATE POLICY "Users can view schedules" ON schedules
    FOR SELECT USING (
        organization_id IN (
            SELECT id FROM organizations WHERE owner_id::text = (SELECT auth.uid())::text
            UNION
            SELECT organization_id FROM users WHERE id::text = (SELECT auth.uid())::text
            UNION
            SELECT organization_id FROM players WHERE user_id::text = (SELECT auth.uid())::text
        )
    );

DROP POLICY IF EXISTS "Owners and Staff can manage schedules" ON schedules;
CREATE POLICY "Owners and Staff can manage schedules" ON schedules
    FOR ALL WITH CHECK (
        organization_id IN (
            SELECT id FROM organizations WHERE owner_id::text = (SELECT auth.uid())::text
            UNION
            SELECT organization_id FROM users WHERE id::text = (SELECT auth.uid())::text AND (account_type = 'team' OR account_type = 'coach')
        )
    );

-- Matches: similar to schedules
DROP POLICY IF EXISTS "Users can view matches" ON matches;
CREATE POLICY "Users can view matches" ON matches
    FOR SELECT USING (
        organization_id IN (
            SELECT id FROM organizations WHERE owner_id::text = (SELECT auth.uid())::text
            UNION
            SELECT organization_id FROM users WHERE id::text = (SELECT auth.uid())::text
            UNION
            SELECT organization_id FROM players WHERE user_id::text = (SELECT auth.uid())::text
        )
    );

DROP POLICY IF EXISTS "Owners and Staff can manage matches" ON matches;
CREATE POLICY "Owners and Staff can manage matches" ON matches
    FOR ALL WITH CHECK (
        organization_id IN (
            SELECT id FROM organizations WHERE owner_id::text = (SELECT auth.uid())::text
            UNION
            SELECT organization_id FROM users WHERE id::text = (SELECT auth.uid())::text AND (account_type = 'team' OR account_type = 'coach')
        )
    );

-- Announcements: viewable by org members
DROP POLICY IF EXISTS "Users can view announcements" ON announcements;
CREATE POLICY "Users can view announcements" ON announcements
    FOR SELECT USING (
        organization_id IN (
            SELECT id FROM organizations WHERE owner_id::text = (SELECT auth.uid())::text
            UNION
            SELECT organization_id FROM users WHERE id::text = (SELECT auth.uid())::text
            UNION
            SELECT organization_id FROM players WHERE user_id::text = (SELECT auth.uid())::text
        )
    );

DROP POLICY IF EXISTS "Owners and Staff can manage announcements" ON announcements;
CREATE POLICY "Owners and Staff can manage announcements" ON announcements
    FOR ALL WITH CHECK (
        organization_id IN (
            SELECT id FROM organizations WHERE owner_id::text = (SELECT auth.uid())::text
            UNION
            SELECT organization_id FROM users WHERE id::text = (SELECT auth.uid())::text AND (account_type = 'team' OR account_type = 'coach')
        )
    );

-- Notifications: generic
DROP POLICY IF EXISTS "Users can manage own notifications" ON notifications;
CREATE POLICY "Users can manage own notifications" ON notifications
    FOR ALL USING (recipient_id::text = (SELECT auth.uid())::text);
-- Triggers
DROP TRIGGER IF EXISTS update_schedules_updated_at ON schedules;
CREATE TRIGGER update_schedules_updated_at
    BEFORE UPDATE ON schedules
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

DROP TRIGGER IF EXISTS update_matches_updated_at ON matches;
CREATE TRIGGER update_matches_updated_at
    BEFORE UPDATE ON matches
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

-- ============================================
-- ACTIVITIES TABLE
-- ============================================
CREATE TABLE IF NOT EXISTS activities (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    player_id UUID REFERENCES players(id) ON DELETE CASCADE,
    type TEXT NOT NULL,
    description TEXT,
    date TIMESTAMPTZ DEFAULT NOW(),
    metadata JSONB,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_activities_player ON activities(player_id);

ALTER TABLE activities ENABLE ROW LEVEL SECURITY;

-- Activities: viewable by self or org owner
DROP POLICY IF EXISTS "Users can view activities" ON activities;
CREATE POLICY "Users can view activities" ON activities
    FOR SELECT USING (
        player_id IN (
            SELECT id FROM players WHERE user_id::text = (SELECT auth.uid())::text
            OR organization_id IN (
                SELECT id FROM organizations WHERE owner_id::text = (SELECT auth.uid())::text
            )
        )
    );

DROP POLICY IF EXISTS "Players can manage own activities" ON activities;
CREATE POLICY "Players can manage own activities" ON activities
    FOR ALL WITH CHECK (
        player_id IN (
            SELECT id FROM players WHERE user_id::text = (SELECT auth.uid())::text
        )
    );
-- ============================================
-- PERSONAL ANALYSES TABLE (Standalone for personal accounts)
-- ============================================
CREATE TABLE IF NOT EXISTS personal_analyses (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    job_id UUID UNIQUE NOT NULL,
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    status TEXT NOT NULL,
    results_json JSONB,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_personal_analyses_user ON personal_analyses(user_id);
CREATE INDEX IF NOT EXISTS idx_personal_analyses_job ON personal_analyses(job_id);

ALTER TABLE personal_analyses ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS "Users can manage own personal analyses" ON personal_analyses;
CREATE POLICY "Users can manage own personal analyses" ON personal_analyses
    FOR ALL USING ((SELECT auth.uid())::text = user_id::text);

-- Triggers
DROP TRIGGER IF EXISTS update_personal_analyses_updated_at ON personal_analyses;
CREATE TRIGGER update_personal_analyses_updated_at
    BEFORE UPDATE ON personal_analyses
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

-- ==========================================
-- STORAGE BUCKETS SETUP
-- ==========================================

-- Create the team-analysis-videos bucket for annotated outputs
INSERT INTO storage.buckets (id, name, public)
VALUES ('team-analysis-videos', 'team-analysis-videos', true)
ON CONFLICT (id) DO NOTHING;

-- RLS Policies for the storage.objects table for the new bucket
-- Drop existing policies first to avoid errors if re-run
DROP POLICY IF EXISTS "Public Access Team Videos" ON storage.objects;
DROP POLICY IF EXISTS "Allow Uploads Team Videos" ON storage.objects;
DROP POLICY IF EXISTS "Allow Updates Team Videos" ON storage.objects;
DROP POLICY IF EXISTS "Allow Deletes Team Videos" ON storage.objects;

-- Allow public access to read files
CREATE POLICY "Public Access Team Videos" ON storage.objects
FOR SELECT
USING (bucket_id = 'team-analysis-videos');

-- Allow all users (including anon backend) to upload files
CREATE POLICY "Allow Uploads Team Videos" ON storage.objects
FOR INSERT
WITH CHECK (bucket_id = 'team-analysis-videos');

-- Allow updates
CREATE POLICY "Allow Updates Team Videos" ON storage.objects
FOR UPDATE
USING (bucket_id = 'team-analysis-videos');

-- Allow deletes
CREATE POLICY "Allow Deletes Team Videos" ON storage.objects
FOR DELETE
USING (bucket_id = 'team-analysis-videos');

-- End of schema

-- ==========================================
-- UPDATE EXISTING TABLES
-- ==========================================
-- Run this to update your existing videos table
ALTER TABLE videos ADD COLUMN IF NOT EXISTS annotated_url TEXT;
