-- Add printed tickets support
-- This migration adds support for printed tickets with barcodes

-- Create printed_tickets table
CREATE TABLE printed_tickets (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  barcode_number TEXT NOT NULL UNIQUE,
  event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
  ticket_type_id UUID NOT NULL REFERENCES ticket_types(id) ON DELETE CASCADE,
  organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
  status TEXT NOT NULL DEFAULT 'valid' CHECK (status IN ('valid', 'used', 'invalid')),
  batch_number TEXT,
  notes TEXT,
  issued_by UUID REFERENCES users(id),
  checked_in_at TIMESTAMP WITH TIME ZONE,
  scanned_by UUID REFERENCES users(id),
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create scan_attempts table for audit logging
CREATE TABLE scan_attempts (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  barcode_number TEXT NOT NULL,
  event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
  scanned_by UUID REFERENCES users(id),
  result TEXT NOT NULL CHECK (result IN ('SUCCESS', 'INVALID_BARCODE', 'WRONG_EVENT', 'ALREADY_USED', 'NOT_VALID')),
  error_message TEXT,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Add indexes for performance
CREATE INDEX idx_printed_tickets_barcode ON printed_tickets(barcode_number);
CREATE INDEX idx_printed_tickets_event_id ON printed_tickets(event_id);
CREATE INDEX idx_printed_tickets_org_id ON printed_tickets(organization_id);
CREATE INDEX idx_scan_attempts_barcode ON scan_attempts(barcode_number);
CREATE INDEX idx_scan_attempts_event_id ON scan_attempts(event_id);
CREATE INDEX idx_scan_attempts_created_at ON scan_attempts(created_at);

-- Add RLS policies for multi-tenant security
ALTER TABLE printed_tickets ENABLE ROW LEVEL SECURITY;
ALTER TABLE scan_attempts ENABLE ROW LEVEL SECURITY;

-- Policies for printed_tickets
CREATE POLICY "Users can view printed tickets in their organization" ON printed_tickets
  FOR SELECT USING (
    EXISTS (
      SELECT 1 FROM users 
      WHERE users.id = auth.uid() 
      AND users.organization_id = printed_tickets.organization_id
    )
  );

CREATE POLICY "Users can insert printed tickets in their organization" ON printed_tickets
  FOR INSERT WITH CHECK (
    EXISTS (
      SELECT 1 FROM users 
      WHERE users.id = auth.uid() 
      AND users.organization_id = printed_tickets.organization_id
    )
  );

CREATE POLICY "Users can update printed tickets in their organization" ON printed_tickets
  FOR UPDATE USING (
    EXISTS (
      SELECT 1 FROM users 
      WHERE users.id = auth.uid() 
      AND users.organization_id = printed_tickets.organization_id
    )
  );

-- Policies for scan_attempts
CREATE POLICY "Users can view scan attempts in their organization" ON scan_attempts
  FOR SELECT USING (
    EXISTS (
      SELECT 1 FROM users 
      WHERE users.id = auth.uid() 
      AND users.organization_id = (
        SELECT organization_id FROM events WHERE events.id = scan_attempts.event_id
      )
    )
  );

CREATE POLICY "Users can insert scan attempts in their organization" ON scan_attempts
  FOR INSERT WITH CHECK (
    EXISTS (
      SELECT 1 FROM users 
      WHERE users.id = auth.uid() 
      AND users.organization_id = (
        SELECT organization_id FROM events WHERE events.id = scan_attempts.event_id
      )
    )
  );

-- Admin override policies (for users with admin privileges)
CREATE POLICY "Admin can view all printed tickets" ON printed_tickets
  FOR SELECT USING (
    EXISTS (
      SELECT 1 FROM users 
      WHERE users.id = auth.uid() 
      AND users.organization_id IS NULL
    )
  );

CREATE POLICY "Admin can manage all printed tickets" ON printed_tickets
  FOR ALL USING (
    EXISTS (
      SELECT 1 FROM users 
      WHERE users.id = auth.uid() 
      AND users.organization_id IS NULL
    )
  );

CREATE POLICY "Admin can view all scan attempts" ON scan_attempts
  FOR SELECT USING (
    EXISTS (
      SELECT 1 FROM users 
      WHERE users.id = auth.uid() 
      AND users.organization_id IS NULL
    )
  );

-- Create function to automatically set organization_id when inserting printed tickets
CREATE OR REPLACE FUNCTION set_printed_ticket_organization_id()
RETURNS TRIGGER AS $$
BEGIN
  -- Set organization_id from the event
  NEW.organization_id = (
    SELECT organization_id 
    FROM events 
    WHERE id = NEW.event_id
  );
  
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Create trigger to automatically set organization_id
CREATE TRIGGER set_printed_ticket_organization_id_trigger
  BEFORE INSERT ON printed_tickets
  FOR EACH ROW
  EXECUTE FUNCTION set_printed_ticket_organization_id();

-- Create function to update updated_at timestamp
CREATE OR REPLACE FUNCTION update_printed_ticket_updated_at()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Create trigger to update updated_at
CREATE TRIGGER update_printed_ticket_updated_at_trigger
  BEFORE UPDATE ON printed_tickets
  FOR EACH ROW
  EXECUTE FUNCTION update_printed_ticket_updated_at();