-- ═══════════════════════════════════════════════════════════════════════════════════════
-- LOOPUMAN DATABASE SCHEMA - PRODUCTION v4.0
-- Run this ONCE in Supabase SQL Editor
-- ═══════════════════════════════════════════════════════════════════════════════════════

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

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- USERS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS app_users (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  telegram_id VARCHAR(50) UNIQUE,
  phone VARCHAR(20) UNIQUE,
  username VARCHAR(100),
  first_name VARCHAR(100),
  last_name VARCHAR(100),
  email VARCHAR(255),
  
  -- Referral system
  referral_code VARCHAR(20) UNIQUE NOT NULL,
  referred_by UUID REFERENCES app_users(id),
  
  -- Location & wallet
  country VARCHAR(5),
  location VARCHAR(200),
  wallet_address VARCHAR(100),
  gooddollar_wallet VARCHAR(100),
  
  -- Identity verification (Tier 0=basic, 1=telegram, 2=ID+selfie, 3=Self Protocol)
  identity_tier INTEGER DEFAULT 0,
  id_photo VARCHAR(255),
  selfie_photo VARCHAR(255),
  kyc_rejection_reason TEXT,
  
  -- Role flags
  is_worker BOOLEAN DEFAULT TRUE,
  is_requester BOOLEAN DEFAULT FALSE,
  is_ai_agent BOOLEAN DEFAULT FALSE,
  
  -- Stats
  reputation INTEGER DEFAULT 100,
  tasks_completed INTEGER DEFAULT 0,
  tasks_approved INTEGER DEFAULT 0,
  tasks_rejected INTEGER DEFAULT 0,
  tasks_posted INTEGER DEFAULT 0,
  abandons INTEGER DEFAULT 0,
  
  -- Status
  banned_until TIMESTAMP,
  notifications_enabled BOOLEAN DEFAULT TRUE,
  
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_users_telegram ON app_users(telegram_id);
CREATE INDEX IF NOT EXISTS idx_users_phone ON app_users(phone);
CREATE INDEX IF NOT EXISTS idx_users_refcode ON app_users(referral_code);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- VAE BALANCES
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS vae_balances (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID UNIQUE REFERENCES app_users(id) ON DELETE CASCADE,
  available INTEGER DEFAULT 0 CHECK (available >= 0),
  pending INTEGER DEFAULT 0 CHECK (pending >= 0),
  total_earned INTEGER DEFAULT 0,
  total_withdrawn INTEGER DEFAULT 0,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_balances_user ON vae_balances(user_id);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- TRANSACTIONS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS transactions (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  type VARCHAR(50) NOT NULL,
  amount INTEGER NOT NULL,
  task_id UUID,
  description TEXT,
  metadata JSONB DEFAULT '{}',
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_tx_user ON transactions(user_id);
CREATE INDEX IF NOT EXISTS idx_tx_type ON transactions(type);
CREATE INDEX IF NOT EXISTS idx_tx_created ON transactions(created_at);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- STRIPE TRANSACTIONS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS stripe_transactions (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  stripe_session_id VARCHAR(255) UNIQUE NOT NULL,
  amount_usd DECIMAL(10,2) NOT NULL,
  amount_vae INTEGER NOT NULL,
  platform_fee_usd DECIMAL(10,2) NOT NULL,
  status VARCHAR(20) DEFAULT 'pending',
  completed_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_stripe_session ON stripe_transactions(stripe_session_id);
CREATE INDEX IF NOT EXISTS idx_stripe_user ON stripe_transactions(user_id);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- TASKS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS tasks (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  requester_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  
  title VARCHAR(200) NOT NULL,
  description TEXT NOT NULL,
  private_description TEXT,
  private_contact VARCHAR(200),
  private_location VARCHAR(200),
  
  category VARCHAR(50) NOT NULL,
  budget INTEGER NOT NULL,
  
  is_local BOOLEAN DEFAULT FALSE,
  location VARCHAR(200),
  
  -- GPS verification for local tasks
  latitude DECIMAL(10, 8),
  longitude DECIMAL(11, 8),
  max_distance_meters INTEGER DEFAULT 500,
  requires_gps BOOLEAN DEFAULT FALSE,
  
  max_workers INTEGER DEFAULT 2,
  current_workers INTEGER DEFAULT 0,
  
  is_reimbursement BOOLEAN DEFAULT FALSE,
  max_reimbursement INTEGER DEFAULT 0,
  
  -- AI moderation
  ai_moderation_score INTEGER,
  ai_moderation_flags TEXT[],
  
  status VARCHAR(20) DEFAULT 'active',
  expires_at TIMESTAMP,
  
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_tasks_requester ON tasks(requester_id);
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
CREATE INDEX IF NOT EXISTS idx_tasks_category ON tasks(category);
CREATE INDEX IF NOT EXISTS idx_tasks_expires ON tasks(expires_at);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- SUBMISSIONS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS submissions (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  task_id UUID REFERENCES tasks(id) ON DELETE CASCADE,
  worker_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  
  status VARCHAR(30) DEFAULT 'in_progress',
  
  content TEXT,
  attachments TEXT[] DEFAULT '{}',
  
  accepted_at TIMESTAMP,
  submitted_at TIMESTAMP,
  approved_at TIMESTAMP,
  rejected_at TIMESTAMP,
  revision_requested_at TIMESTAMP,
  abandoned_at TIMESTAMP,
  
  rating INTEGER,
  requester_rating INTEGER,
  feedback TEXT,
  rejection_reason TEXT,
  
  worker_payment INTEGER,
  platform_fee INTEGER,
  
  is_ai BOOLEAN DEFAULT FALSE,
  
  -- GPS verification for local tasks
  worker_latitude DECIMAL(10, 8),
  worker_longitude DECIMAL(11, 8),
  gps_verified BOOLEAN DEFAULT FALSE,
  gps_distance_meters INTEGER,
  gps_verified_at TIMESTAMP,
  
  -- AI moderation
  ai_quality_score INTEGER,
  ai_moderation_flags TEXT[],
  
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW(),
  
  UNIQUE(task_id, worker_id)
);

CREATE INDEX IF NOT EXISTS idx_sub_task ON submissions(task_id);
CREATE INDEX IF NOT EXISTS idx_sub_worker ON submissions(worker_id);
CREATE INDEX IF NOT EXISTS idx_sub_status ON submissions(status);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- MESSAGES (between worker & requester)
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS messages (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  submission_id UUID REFERENCES submissions(id) ON DELETE CASCADE,
  sender_id UUID REFERENCES app_users(id),
  content TEXT NOT NULL,
  attachments TEXT[] DEFAULT '{}',
  read BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_messages_sub ON messages(submission_id);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- TASK QUESTIONS (before accepting)
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS task_questions (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  task_id UUID REFERENCES tasks(id) ON DELETE CASCADE,
  asker_id UUID REFERENCES app_users(id),
  question TEXT NOT NULL,
  answer TEXT,
  answered_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT NOW()
);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- TIPS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS tips (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  from_user_id UUID REFERENCES app_users(id),
  to_user_id UUID REFERENCES app_users(id),
  amount INTEGER NOT NULL,
  task_id UUID REFERENCES tasks(id),
  created_at TIMESTAMP DEFAULT NOW()
);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- DISPUTES
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS disputes (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  submission_id UUID REFERENCES submissions(id) ON DELETE CASCADE,
  worker_id UUID REFERENCES app_users(id),
  reason TEXT NOT NULL,
  status VARCHAR(20) DEFAULT 'open',
  resolution TEXT,
  ai_recommendation TEXT,
  resolved_by UUID REFERENCES app_users(id),
  resolved_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_disputes_status ON disputes(status);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- WITHDRAWALS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS withdrawals (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  amount_vae INTEGER NOT NULL,
  amount_usd DECIMAL(10,2) NOT NULL,
  stablecoin VARCHAR(10) NOT NULL,
  wallet_address VARCHAR(100) NOT NULL,
  status VARCHAR(20) DEFAULT 'pending',
  tx_hash VARCHAR(100),
  failure_reason TEXT,
  completed_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_withdrawals_user ON withdrawals(user_id);
CREATE INDEX IF NOT EXISTS idx_withdrawals_status ON withdrawals(status);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- REFERRALS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS referrals (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  referrer_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  referee_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  created_at TIMESTAMP DEFAULT NOW(),
  UNIQUE(referrer_id, referee_id)
);

CREATE INDEX IF NOT EXISTS idx_referrals_referrer ON referrals(referrer_id);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- REFERRAL EARNINGS (track 1% lifetime bonus)
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS referral_earnings (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  referrer_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  referee_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  source_transaction_id UUID REFERENCES transactions(id),
  amount INTEGER NOT NULL,
  processed BOOLEAN DEFAULT FALSE,
  processed_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_ref_earnings_referrer ON referral_earnings(referrer_id);
CREATE INDEX IF NOT EXISTS idx_ref_earnings_processed ON referral_earnings(processed);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- WORKER SKILLS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS worker_skills (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID UNIQUE REFERENCES app_users(id) ON DELETE CASCADE,
  categories TEXT[] DEFAULT '{}',
  raw_description TEXT,
  quality_score INTEGER DEFAULT 50,
  experience VARCHAR(20) DEFAULT 'beginner',
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- BADGES
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS user_badges (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  badge_id VARCHAR(50) NOT NULL,
  earned_at TIMESTAMP DEFAULT NOW(),
  UNIQUE(user_id, badge_id)
);

CREATE INDEX IF NOT EXISTS idx_badges_user ON user_badges(user_id);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- REPUTATION ATTESTATIONS (on-chain)
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS reputation_attestations (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  milestone VARCHAR(50) NOT NULL,
  tasks_at_time INTEGER NOT NULL,
  tx_hash VARCHAR(100),
  status VARCHAR(20) DEFAULT 'pending',
  error_message TEXT,
  created_at TIMESTAMP DEFAULT NOW(),
  UNIQUE(user_id, milestone)
);

CREATE INDEX IF NOT EXISTS idx_attestations_user ON reputation_attestations(user_id);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- SUPPORT TICKETS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS support_tickets (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  ticket_id VARCHAR(20) UNIQUE NOT NULL,
  user_id UUID REFERENCES app_users(id) ON DELETE CASCADE,
  subject VARCHAR(200) NOT NULL,
  message TEXT NOT NULL,
  status VARCHAR(20) DEFAULT 'open',
  response TEXT,
  responded_by UUID REFERENCES app_users(id),
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_tickets_status ON support_tickets(status);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- MODERATION LOGS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS moderation_logs (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  entity_type VARCHAR(20) NOT NULL,
  entity_id UUID NOT NULL,
  action VARCHAR(50) NOT NULL,
  reason TEXT,
  ai_generated BOOLEAN DEFAULT FALSE,
  moderator_id UUID REFERENCES app_users(id),
  metadata JSONB DEFAULT '{}',
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_mod_entity ON moderation_logs(entity_type, entity_id);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- FRAUD ALERTS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS fraud_alerts (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID REFERENCES app_users(id),
  alert_type VARCHAR(50) NOT NULL,
  severity VARCHAR(20) NOT NULL,
  details JSONB NOT NULL,
  resolved BOOLEAN DEFAULT FALSE,
  resolved_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_fraud_resolved ON fraud_alerts(resolved);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- SYSTEM ALERTS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS system_alerts (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  service VARCHAR(50) NOT NULL,
  level VARCHAR(20) NOT NULL,
  message TEXT NOT NULL,
  metadata JSONB DEFAULT '{}',
  acknowledged BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMP DEFAULT NOW()
);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- ADMIN ACTIONS LOG
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS admin_actions (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  admin_id VARCHAR(50),
  user_id UUID REFERENCES app_users(id),
  action VARCHAR(50) NOT NULL,
  details JSONB DEFAULT '{}',
  created_at TIMESTAMP DEFAULT NOW()
);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- VIEWS FOR ANALYTICS
-- ═══════════════════════════════════════════════════════════════════════════════════════

CREATE OR REPLACE VIEW daily_stats AS
SELECT 
  DATE(created_at) as date,
  COUNT(*) FILTER (WHERE type = 'task_payment') as tasks_completed,
  SUM(amount) FILTER (WHERE type = 'task_payment') as total_paid_vae,
  COUNT(DISTINCT user_id) as active_users
FROM transactions
WHERE created_at > NOW() - INTERVAL '30 days'
GROUP BY DATE(created_at)
ORDER BY date DESC;

CREATE OR REPLACE VIEW user_leaderboard AS
SELECT 
  u.id,
  u.username,
  u.first_name,
  u.tasks_completed,
  u.reputation,
  b.total_earned
FROM app_users u
JOIN vae_balances b ON u.id = b.user_id
WHERE u.is_ai_agent = FALSE
ORDER BY b.total_earned DESC
LIMIT 100;

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- HELPER FUNCTIONS
-- ═══════════════════════════════════════════════════════════════════════════════════════

-- Function to get user's withdrawal limit based on identity tier
CREATE OR REPLACE FUNCTION get_withdrawal_limit(tier INTEGER)
RETURNS INTEGER AS $$
BEGIN
  CASE tier
    WHEN 0 THEN RETURN 1000;   -- $10/month (Tier 0: Telegram only)
    WHEN 1 THEN RETURN 10000;  -- $100/month (Tier 1: GoodDollar)
    WHEN 2 THEN RETURN 50000;  -- $500/month (Tier 2: ID+Selfie)
    WHEN 3 THEN RETURN NULL;   -- Unlimited (Tier 3: Self Protocol)
    ELSE RETURN 1000;
  END CASE;
END;
$$ LANGUAGE plpgsql;

-- Function to calculate monthly withdrawal total
CREATE OR REPLACE FUNCTION get_monthly_withdrawn(uid UUID)
RETURNS INTEGER AS $$
DECLARE
  total INTEGER;
BEGIN
  SELECT COALESCE(SUM(amount_vae), 0) INTO total
  FROM withdrawals
  WHERE user_id = uid
    AND status = 'completed'
    AND created_at > NOW() - INTERVAL '30 days';
  RETURN total;
END;
$$ LANGUAGE plpgsql;

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- ROW LEVEL SECURITY
-- ═══════════════════════════════════════════════════════════════════════════════════════

ALTER TABLE app_users ENABLE ROW LEVEL SECURITY;
ALTER TABLE vae_balances ENABLE ROW LEVEL SECURITY;
ALTER TABLE transactions ENABLE ROW LEVEL SECURITY;
ALTER TABLE tasks ENABLE ROW LEVEL SECURITY;
ALTER TABLE submissions ENABLE ROW LEVEL SECURITY;
ALTER TABLE stripe_transactions ENABLE ROW LEVEL SECURITY;
ALTER TABLE withdrawals ENABLE ROW LEVEL SECURITY;

-- Service role has full access (for backend)
CREATE POLICY "Service role full access" ON app_users FOR ALL USING (true);
CREATE POLICY "Service role full access" ON vae_balances FOR ALL USING (true);
CREATE POLICY "Service role full access" ON transactions FOR ALL USING (true);
CREATE POLICY "Service role full access" ON tasks FOR ALL USING (true);
CREATE POLICY "Service role full access" ON submissions FOR ALL USING (true);
CREATE POLICY "Service role full access" ON stripe_transactions FOR ALL USING (true);
CREATE POLICY "Service role full access" ON withdrawals FOR ALL USING (true);

-- ═══════════════════════════════════════════════════════════════════════════════════════
-- DONE!
-- ═══════════════════════════════════════════════════════════════════════════════════════
