-- =====================================================
-- TABLE: education.videos
-- =====================================================
-- Proyecto: OrbiQuant IA (Trading Platform)
-- Módulo: OQI-002 - Education
-- Especificación: ET-EDU-008-video-upload-architecture.md
-- Blocker: BLOCKER-003 (ST4.3)
-- =====================================================

CREATE TABLE education.videos (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

  -- Relaciones
  course_id UUID NOT NULL REFERENCES education.courses(id) ON DELETE CASCADE,
  lesson_id UUID REFERENCES education.lessons(id) ON DELETE SET NULL,
  uploaded_by UUID NOT NULL REFERENCES auth.users(id) ON DELETE RESTRICT,

  -- Información básica
  title VARCHAR(200) NOT NULL,
  description TEXT,
  original_filename VARCHAR(500) NOT NULL,

  -- Storage (S3/R2)
  storage_provider VARCHAR(50) NOT NULL DEFAULT 's3', -- 's3', 'r2', 'cloudflare_stream'
  storage_bucket VARCHAR(200) NOT NULL,
  storage_key VARCHAR(500) NOT NULL, -- S3/R2 key (path)
  storage_region VARCHAR(50),

  -- File info
  file_size_bytes BIGINT NOT NULL,
  mime_type VARCHAR(100) NOT NULL DEFAULT 'video/mp4',
  duration_seconds INTEGER, -- Detectado después de upload

  -- Status & Processing
  status VARCHAR(50) NOT NULL DEFAULT 'uploading',
    -- 'uploading', 'uploaded', 'processing', 'ready', 'error', 'deleted'
  processing_started_at TIMESTAMPTZ,
  processing_completed_at TIMESTAMPTZ,
  processing_error TEXT,

  -- CDN & URLs
  cdn_url VARCHAR(1000), -- URL pública del video (CDN)
  thumbnail_url VARCHAR(1000),

  -- Transcoded versions (múltiples resoluciones)
  transcoded_versions JSONB,
    -- Ejemplo: [
    --   {resolution: "1080p", storage_key: "...", cdn_url: "...", file_size_bytes: 123456},
    --   {resolution: "720p", storage_key: "...", cdn_url: "...", file_size_bytes: 67890},
    --   {resolution: "480p", storage_key: "...", cdn_url: "...", file_size_bytes: 34567}
    -- ]

  -- Metadata educativo
  metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
    -- Ejemplo: {
    --   "tags": ["trading", "stocks", "technical-analysis"],
    --   "language": "en",
    --   "difficulty": "intermediate",
    --   "captions": [{language: "en", url: "...srt"}, {language: "es", url: "...srt"}],
    --   "transcript": "Full text transcript...",
    --   "video_codec": "h264",
    --   "audio_codec": "aac",
    --   "bitrate_kbps": 5000,
    --   "fps": 30,
    --   "resolution": "1920x1080"
    -- }

  -- Multipart upload tracking
  upload_id VARCHAR(500), -- AWS/R2 multipart upload ID
  upload_parts_completed INTEGER DEFAULT 0,
  upload_parts_total INTEGER,
  upload_progress_percent INTEGER DEFAULT 0,

  -- Timestamps
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  uploaded_at TIMESTAMPTZ, -- Cuando se completó el upload
  deleted_at TIMESTAMPTZ, -- Soft delete

  -- Constraints
  CONSTRAINT valid_status CHECK (status IN ('uploading', 'uploaded', 'processing', 'ready', 'error', 'deleted')),
  CONSTRAINT valid_storage_provider CHECK (storage_provider IN ('s3', 'r2', 'cloudflare_stream')),
  CONSTRAINT valid_progress CHECK (upload_progress_percent >= 0 AND upload_progress_percent <= 100),
  CONSTRAINT positive_duration CHECK (duration_seconds IS NULL OR duration_seconds > 0),
  CONSTRAINT positive_file_size CHECK (file_size_bytes > 0)
);

-- Índices
CREATE INDEX idx_videos_course ON education.videos(course_id);
CREATE INDEX idx_videos_lesson ON education.videos(lesson_id);
CREATE INDEX idx_videos_uploader ON education.videos(uploaded_by);
CREATE INDEX idx_videos_status ON education.videos(status);
CREATE INDEX idx_videos_created ON education.videos(created_at DESC);
CREATE INDEX idx_videos_storage_key ON education.videos(storage_key);

-- Índice GIN para búsqueda en metadata (tags, language, etc.)
CREATE INDEX idx_videos_metadata ON education.videos USING GIN (metadata jsonb_path_ops);

-- Índice para soft delete (excluir deleted)
CREATE INDEX idx_videos_active ON education.videos(id) WHERE deleted_at IS NULL;

-- Índice compuesto para queries frecuentes
CREATE INDEX idx_videos_course_status ON education.videos(course_id, status) WHERE deleted_at IS NULL;

-- Comentarios
COMMENT ON TABLE education.videos IS 'Videos educativos con soporte de multipart upload, transcoding y CDN';
COMMENT ON COLUMN education.videos.storage_key IS 'S3/R2 object key (ruta completa del archivo)';
COMMENT ON COLUMN education.videos.status IS 'uploading: En proceso de upload | uploaded: Upload completo | processing: Transcoding en progreso | ready: Listo para uso | error: Falló processing | deleted: Soft deleted';
COMMENT ON COLUMN education.videos.transcoded_versions IS 'Array de versiones transcodificadas en diferentes resoluciones (1080p, 720p, 480p, etc.)';
COMMENT ON COLUMN education.videos.metadata IS 'Metadata educativo: tags, language, difficulty, captions, transcript, codecs, etc.';
COMMENT ON COLUMN education.videos.upload_id IS 'AWS/R2 multipart upload ID para tracking de upload en progreso';
COMMENT ON COLUMN education.videos.cdn_url IS 'URL pública del video servido desde CDN (CloudFront/Cloudflare)';
COMMENT ON COLUMN education.videos.thumbnail_url IS 'URL del thumbnail generado automáticamente del video';
COMMENT ON COLUMN education.videos.deleted_at IS 'Soft delete: NULL = activo, NOT NULL = eliminado';

-- Función para actualizar updated_at automáticamente
CREATE OR REPLACE FUNCTION education.update_videos_updated_at()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_update_videos_updated_at
  BEFORE UPDATE ON education.videos
  FOR EACH ROW
  EXECUTE FUNCTION education.update_videos_updated_at();

-- Función helper para soft delete
CREATE OR REPLACE FUNCTION education.soft_delete_video(video_uuid UUID)
RETURNS VOID AS $$
BEGIN
  UPDATE education.videos
  SET
    deleted_at = NOW(),
    status = 'deleted',
    updated_at = NOW()
  WHERE id = video_uuid AND deleted_at IS NULL;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION education.soft_delete_video IS 'Soft delete de un video (marca deleted_at en lugar de eliminar el registro)';

-- View para videos activos (excluye soft deleted)
CREATE OR REPLACE VIEW education.active_videos AS
SELECT * FROM education.videos
WHERE deleted_at IS NULL;

COMMENT ON VIEW education.active_videos IS 'Vista de videos activos (excluye soft deleted)';
