-- Add admin system with role-based access control

-- Add user roles
ALTER TABLE users 
ADD COLUMN role VARCHAR(20) DEFAULT 'organizer',
ADD COLUMN is_active BOOLEAN DEFAULT true,
ADD COLUMN last_login TIMESTAMP WITH TIME ZONE,
ADD COLUMN created_by UUID REFERENCES users(id); -- Track who created this user

-- Update existing users to have organizer role
UPDATE users SET role = 'organizer' WHERE role IS NULL;

-- Create admin_settings table for platform configuration
CREATE TABLE admin_settings (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  setting_key TEXT UNIQUE NOT NULL,
  setting_value JSONB NOT NULL,
  description TEXT,
  updated_by UUID REFERENCES users(id),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create audit_logs table for tracking admin actions
CREATE TABLE audit_logs (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID REFERENCES users(id),
  action TEXT NOT NULL, -- 'create', 'update', 'delete', 'view'
  resource_type TEXT NOT NULL, -- 'user', 'organization', 'event', 'ticket'
  resource_id UUID,
  old_values JSONB,
  new_values JSONB,
  ip_address INET,
  user_agent TEXT,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create platform_stats view for admin dashboard
CREATE VIEW platform_stats AS
SELECT 
  (SELECT COUNT(*) FROM users WHERE role = 'organizer' AND is_active = true) as active_organizers,
  (SELECT COUNT(*) FROM users WHERE role = 'admin') as admin_users,
  (SELECT COUNT(*) FROM organizations) as total_organizations,
  (SELECT COUNT(*) FROM events) as total_events,
  (SELECT COUNT(*) FROM events WHERE start_time >= NOW()) as upcoming_events,
  (SELECT COUNT(*) FROM tickets) as total_tickets_sold,
  (SELECT COALESCE(SUM(price), 0) FROM tickets) as total_revenue,
  (SELECT COALESCE(SUM(platform_fee_charged), 0) FROM tickets) as total_platform_fees,
  (SELECT COUNT(DISTINCT DATE(created_at)) FROM tickets WHERE created_at >= NOW() - INTERVAL '30 days') as active_days_last_30,
  (SELECT COUNT(*) FROM users WHERE created_at >= NOW() - INTERVAL '7 days') as new_users_last_7_days;

-- Update RLS policies for admin access
-- Users table - admins can view all users
CREATE POLICY "Admins can view all users" ON users
  FOR SELECT USING (
    auth.uid() IN (SELECT id FROM users WHERE role = 'admin') OR
    id = auth.uid()
  );

CREATE POLICY "Admins can update any user" ON users
  FOR UPDATE USING (
    auth.uid() IN (SELECT id FROM users WHERE role = 'admin') OR
    id = auth.uid()
  );

CREATE POLICY "Admins can create users" ON users
  FOR INSERT WITH CHECK (
    auth.uid() IN (SELECT id FROM users WHERE role = 'admin')
  );

-- Organizations table - admins can view all organizations
CREATE POLICY "Admins can view all organizations" ON organizations
  FOR SELECT USING (
    auth.uid() IN (SELECT id FROM users WHERE role = 'admin') OR
    id IN (SELECT organization_id FROM users WHERE id = auth.uid())
  );

CREATE POLICY "Admins can update any organization" ON organizations
  FOR UPDATE USING (
    auth.uid() IN (SELECT id FROM users WHERE role = 'admin') OR
    id IN (SELECT organization_id FROM users WHERE id = auth.uid())
  );

-- Events table - admins can view all events
CREATE POLICY "Admins can view all events" ON events
  FOR SELECT USING (
    auth.uid() IN (SELECT id FROM users WHERE role = 'admin') OR
    organization_id IN (SELECT organization_id FROM users WHERE id = auth.uid())
  );

-- Tickets table - admins can view all tickets
CREATE POLICY "Admins can view all tickets" ON tickets
  FOR SELECT USING (
    auth.uid() IN (SELECT id FROM users WHERE role = 'admin') OR
    event_id IN (
      SELECT id FROM events WHERE organization_id IN (
        SELECT organization_id FROM users WHERE id = auth.uid()
      )
    )
  );

-- Enable RLS on new tables
ALTER TABLE audit_logs ENABLE ROW LEVEL SECURITY;
ALTER TABLE admin_settings ENABLE ROW LEVEL SECURITY;

-- RLS Policies for audit_logs
CREATE POLICY "Admins can view all audit logs" ON audit_logs
  FOR SELECT USING (auth.uid() IN (SELECT id FROM users WHERE role = 'admin'));

CREATE POLICY "System can create audit logs" ON audit_logs
  FOR INSERT WITH CHECK (true);

-- RLS Policies for admin_settings
CREATE POLICY "Admins can manage settings" ON admin_settings
  FOR ALL USING (auth.uid() IN (SELECT id FROM users WHERE role = 'admin'));

-- Insert default admin settings
INSERT INTO admin_settings (setting_key, setting_value, description) VALUES
('platform_name', '"Black Canyon Tickets"', 'Platform display name'),
('platform_email', '"support@blackcanyontickets.com"', 'Platform support email'),
('default_platform_fee_percentage', '0.03', 'Default platform fee percentage'),
('default_platform_fee_fixed', '30', 'Default platform fee fixed amount in cents'),
('max_events_per_organization', '100', 'Maximum events per organization'),
('email_notifications_enabled', 'true', 'Enable email notifications'),
('maintenance_mode', 'false', 'Platform maintenance mode');

-- Create function to log admin actions
CREATE OR REPLACE FUNCTION log_admin_action(
  p_action TEXT,
  p_resource_type TEXT,
  p_resource_id UUID DEFAULT NULL,
  p_old_values JSONB DEFAULT NULL,
  p_new_values JSONB DEFAULT NULL
) RETURNS VOID AS $$
BEGIN
  INSERT INTO audit_logs (user_id, action, resource_type, resource_id, old_values, new_values)
  VALUES (auth.uid(), p_action, p_resource_type, p_resource_id, p_old_values, p_new_values);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Create function to check if user is admin
CREATE OR REPLACE FUNCTION is_admin(user_uuid UUID DEFAULT auth.uid())
RETURNS BOOLEAN AS $$
BEGIN
  RETURN EXISTS (
    SELECT 1 FROM users 
    WHERE id = user_uuid AND role = 'admin' AND is_active = true
  );
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Create indexes for performance
CREATE INDEX idx_users_role ON users(role);
CREATE INDEX idx_users_is_active ON users(is_active);
CREATE INDEX idx_users_last_login ON users(last_login);
CREATE INDEX idx_audit_logs_user_id ON audit_logs(user_id);
CREATE INDEX idx_audit_logs_resource_type ON audit_logs(resource_type);
CREATE INDEX idx_audit_logs_created_at ON audit_logs(created_at);
CREATE INDEX idx_admin_settings_key ON admin_settings(setting_key);

-- Update the auth signup function to handle admin creation
CREATE OR REPLACE FUNCTION handle_auth_signup()
RETURNS TRIGGER AS $$
DECLARE
  user_role TEXT := 'organizer';
BEGIN
  -- Check if this is the first user (make them admin)
  IF NOT EXISTS (SELECT 1 FROM users LIMIT 1) THEN
    user_role := 'admin';
  END IF;

  -- Create user record in users table with error handling
  INSERT INTO users (id, email, name, role)
  VALUES (
    NEW.id, 
    NEW.email, 
    COALESCE(NEW.raw_user_meta_data->>'name', NEW.email),
    user_role
  )
  ON CONFLICT (id) DO UPDATE SET
    email = EXCLUDED.email,
    name = COALESCE(EXCLUDED.name, users.name),
    last_login = NOW();
  
  RETURN NEW;
EXCEPTION
  WHEN OTHERS THEN
    -- Log the error but don't fail the auth process
    RAISE WARNING 'Failed to create user record for %: %', NEW.email, SQLERRM;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Add comments for clarity
COMMENT ON COLUMN users.role IS 'User role: admin, organizer, staff';
COMMENT ON COLUMN users.is_active IS 'Whether the user account is active';
COMMENT ON COLUMN users.created_by IS 'Admin user who created this account';
COMMENT ON TABLE audit_logs IS 'Audit trail for admin actions';
COMMENT ON TABLE admin_settings IS 'Platform-wide configuration settings';
COMMENT ON VIEW platform_stats IS 'Aggregated platform statistics for admin dashboard';