-- =====================================================
-- SCHEMA: billing
-- PROPÓSITO: Suscripciones SaaS, planes, pagos, facturación
-- MÓDULOS: MGN-015 (Billing y Suscripciones)
-- FECHA: 2025-11-24
-- =====================================================
-- NOTA: Este schema permite que el sistema opere como SaaS multi-tenant
-- o como instalación single-tenant (on-premise). En modo single-tenant,
-- las tablas de este schema pueden ignorarse o tener un único plan "unlimited".
-- =====================================================

-- Crear schema
CREATE SCHEMA IF NOT EXISTS billing;

-- =====================================================
-- TYPES (ENUMs)
-- =====================================================

CREATE TYPE billing.subscription_status AS ENUM (
  'trialing',      -- En período de prueba
  'active',        -- Suscripción activa
  'past_due',      -- Pago atrasado
  'paused',        -- Suscripción pausada
  'cancelled',     -- Cancelada por usuario
  'suspended',     -- Suspendida por falta de pago
  'expired'        -- Expirada
);

CREATE TYPE billing.billing_cycle AS ENUM (
  'monthly',
  'quarterly',
  'semi_annual',
  'annual'
);

CREATE TYPE billing.payment_method_type AS ENUM (
  'card',
  'bank_transfer',
  'paypal',
  'oxxo',           -- México
  'spei',           -- México
  'other'
);

CREATE TYPE billing.invoice_status AS ENUM (
  'draft',
  'open',
  'paid',
  'void',
  'uncollectible'
);

CREATE TYPE billing.payment_status AS ENUM (
  'pending',
  'processing',
  'succeeded',
  'failed',
  'cancelled',
  'refunded'
);

-- =====================================================
-- TABLES
-- =====================================================

-- Tabla: subscription_plans (Planes disponibles - global, no por tenant)
-- Esta tabla no tiene tenant_id porque los planes son globales del sistema SaaS
CREATE TABLE billing.subscription_plans (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  code VARCHAR(50) UNIQUE NOT NULL,
  name VARCHAR(100) NOT NULL,
  description TEXT,

  -- Precios
  price_monthly DECIMAL(12,2) NOT NULL DEFAULT 0,
  price_yearly DECIMAL(12,2) NOT NULL DEFAULT 0,
  currency_code VARCHAR(3) NOT NULL DEFAULT 'MXN',

  -- Límites
  max_users INTEGER DEFAULT 10,
  max_companies INTEGER DEFAULT 1,
  max_storage_gb INTEGER DEFAULT 5,
  max_api_calls_month INTEGER DEFAULT 10000,

  -- Características incluidas (JSON para flexibilidad)
  features JSONB DEFAULT '{}'::jsonb,
  -- Ejemplo: {"inventory": true, "sales": true, "financial": true, "purchase": true, "crm": false}

  -- Metadata
  is_active BOOLEAN NOT NULL DEFAULT true,
  is_public BOOLEAN NOT NULL DEFAULT true,  -- Visible en página de precios
  is_default BOOLEAN NOT NULL DEFAULT false, -- Plan por defecto para nuevos tenants
  trial_days INTEGER DEFAULT 14,
  sort_order INTEGER DEFAULT 0,

  -- Auditoría
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID,
  updated_at TIMESTAMP,
  updated_by UUID,

  CONSTRAINT chk_plans_price_monthly CHECK (price_monthly >= 0),
  CONSTRAINT chk_plans_price_yearly CHECK (price_yearly >= 0),
  CONSTRAINT chk_plans_max_users CHECK (max_users > 0 OR max_users IS NULL),
  CONSTRAINT chk_plans_trial_days CHECK (trial_days >= 0)
);

-- Tabla: tenant_owners (Propietarios/Contratantes de tenant)
-- Usuario(s) que contratan y pagan por el tenant
CREATE TABLE billing.tenant_owners (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  ownership_type VARCHAR(20) NOT NULL DEFAULT 'owner',
  -- owner: Propietario principal (puede haber solo 1)
  -- billing_admin: Puede gestionar facturación

  -- Contacto de facturación (puede diferir del usuario)
  billing_email VARCHAR(255),
  billing_phone VARCHAR(50),
  billing_name VARCHAR(255),

  -- Auditoría
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID,

  CONSTRAINT uq_tenant_owners UNIQUE (tenant_id, user_id),
  CONSTRAINT chk_ownership_type CHECK (ownership_type IN ('owner', 'billing_admin'))
);

-- Tabla: subscriptions (Suscripciones activas de cada tenant)
CREATE TABLE billing.subscriptions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  plan_id UUID NOT NULL REFERENCES billing.subscription_plans(id),

  -- Estado
  status billing.subscription_status NOT NULL DEFAULT 'trialing',
  billing_cycle billing.billing_cycle NOT NULL DEFAULT 'monthly',

  -- Fechas importantes
  trial_start_at TIMESTAMP,
  trial_end_at TIMESTAMP,
  current_period_start TIMESTAMP NOT NULL,
  current_period_end TIMESTAMP NOT NULL,
  cancelled_at TIMESTAMP,
  cancel_at_period_end BOOLEAN NOT NULL DEFAULT false,
  paused_at TIMESTAMP,

  -- Descuentos/Cupones
  discount_percent DECIMAL(5,2) DEFAULT 0,
  coupon_code VARCHAR(50),

  -- Integración pasarela de pago
  stripe_subscription_id VARCHAR(255),
  stripe_customer_id VARCHAR(255),

  -- Auditoría
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID,
  updated_at TIMESTAMP,
  updated_by UUID,

  CONSTRAINT uq_subscriptions_tenant UNIQUE (tenant_id), -- Solo 1 suscripción activa por tenant
  CONSTRAINT chk_subscriptions_discount CHECK (discount_percent >= 0 AND discount_percent <= 100),
  CONSTRAINT chk_subscriptions_period CHECK (current_period_end > current_period_start)
);

-- Tabla: payment_methods (Métodos de pago por tenant)
CREATE TABLE billing.payment_methods (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

  type billing.payment_method_type NOT NULL,
  is_default BOOLEAN NOT NULL DEFAULT false,

  -- Información de tarjeta (solo últimos 4 dígitos por seguridad)
  card_last_four VARCHAR(4),
  card_brand VARCHAR(20),  -- visa, mastercard, amex
  card_exp_month INTEGER,
  card_exp_year INTEGER,

  -- Dirección de facturación
  billing_name VARCHAR(255),
  billing_email VARCHAR(255),
  billing_address_line1 VARCHAR(255),
  billing_address_line2 VARCHAR(255),
  billing_city VARCHAR(100),
  billing_state VARCHAR(100),
  billing_postal_code VARCHAR(20),
  billing_country VARCHAR(2),  -- ISO 3166-1 alpha-2

  -- Integración pasarela
  stripe_payment_method_id VARCHAR(255),

  -- Auditoría
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID,
  updated_at TIMESTAMP,
  deleted_at TIMESTAMP,  -- Soft delete

  CONSTRAINT chk_payment_methods_card_exp CHECK (
    (type != 'card') OR
    (card_exp_month BETWEEN 1 AND 12 AND card_exp_year >= EXTRACT(YEAR FROM CURRENT_DATE))
  )
);

-- Tabla: billing_invoices (Facturas de suscripción)
CREATE TABLE billing.invoices (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  subscription_id UUID REFERENCES billing.subscriptions(id),

  -- Número de factura
  invoice_number VARCHAR(50) NOT NULL,

  -- Estado y fechas
  status billing.invoice_status NOT NULL DEFAULT 'draft',
  period_start TIMESTAMP,
  period_end TIMESTAMP,
  due_date DATE NOT NULL,
  paid_at TIMESTAMP,
  voided_at TIMESTAMP,

  -- Montos
  subtotal DECIMAL(12,2) NOT NULL DEFAULT 0,
  tax_amount DECIMAL(12,2) NOT NULL DEFAULT 0,
  discount_amount DECIMAL(12,2) NOT NULL DEFAULT 0,
  total DECIMAL(12,2) NOT NULL DEFAULT 0,
  amount_paid DECIMAL(12,2) NOT NULL DEFAULT 0,
  amount_due DECIMAL(12,2) NOT NULL DEFAULT 0,
  currency_code VARCHAR(3) NOT NULL DEFAULT 'MXN',

  -- Datos fiscales del cliente
  customer_name VARCHAR(255),
  customer_tax_id VARCHAR(50),
  customer_email VARCHAR(255),
  customer_address TEXT,

  -- PDF y CFDI (México)
  pdf_url VARCHAR(500),
  cfdi_uuid VARCHAR(36),  -- UUID del CFDI si aplica
  cfdi_xml_url VARCHAR(500),

  -- Integración pasarela
  stripe_invoice_id VARCHAR(255),

  -- Notas
  notes TEXT,

  -- Auditoría
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID,
  updated_at TIMESTAMP,

  CONSTRAINT uq_invoices_number UNIQUE (invoice_number),
  CONSTRAINT chk_invoices_amounts CHECK (total >= 0 AND subtotal >= 0 AND amount_due >= 0)
);

-- Tabla: invoice_lines (Líneas de detalle de factura)
CREATE TABLE billing.invoice_lines (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  invoice_id UUID NOT NULL REFERENCES billing.invoices(id) ON DELETE CASCADE,

  description VARCHAR(255) NOT NULL,
  quantity DECIMAL(12,4) NOT NULL DEFAULT 1,
  unit_price DECIMAL(12,2) NOT NULL,
  amount DECIMAL(12,2) NOT NULL,

  -- Para facturación por uso
  period_start TIMESTAMP,
  period_end TIMESTAMP,

  -- Auditoría
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

  CONSTRAINT chk_invoice_lines_qty CHECK (quantity > 0),
  CONSTRAINT chk_invoice_lines_price CHECK (unit_price >= 0)
);

-- Tabla: payments (Pagos recibidos)
CREATE TABLE billing.payments (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  invoice_id UUID REFERENCES billing.invoices(id),
  payment_method_id UUID REFERENCES billing.payment_methods(id),

  -- Monto y moneda
  amount DECIMAL(12,2) NOT NULL,
  currency_code VARCHAR(3) NOT NULL DEFAULT 'MXN',

  -- Estado
  status billing.payment_status NOT NULL DEFAULT 'pending',

  -- Fechas
  paid_at TIMESTAMP,
  failed_at TIMESTAMP,
  refunded_at TIMESTAMP,

  -- Detalles del error (si falló)
  failure_reason VARCHAR(255),
  failure_code VARCHAR(50),

  -- Referencia de transacción
  transaction_id VARCHAR(255),
  stripe_payment_intent_id VARCHAR(255),

  -- Auditoría
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

  CONSTRAINT chk_payments_amount CHECK (amount > 0)
);

-- Tabla: usage_records (Registros de uso para billing por consumo)
CREATE TABLE billing.usage_records (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  subscription_id UUID REFERENCES billing.subscriptions(id),

  -- Tipo de métrica
  metric_type VARCHAR(50) NOT NULL,
  -- Ejemplos: 'users', 'storage_gb', 'api_calls', 'invoices_sent', 'emails_sent'

  quantity DECIMAL(12,4) NOT NULL,
  billing_period DATE NOT NULL,  -- Mes de facturación (YYYY-MM-01)

  -- Auditoría
  recorded_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

  CONSTRAINT chk_usage_quantity CHECK (quantity >= 0)
);

-- Tabla: coupons (Cupones de descuento)
CREATE TABLE billing.coupons (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  code VARCHAR(50) UNIQUE NOT NULL,
  name VARCHAR(100) NOT NULL,
  description TEXT,

  -- Tipo de descuento
  discount_type VARCHAR(20) NOT NULL DEFAULT 'percent',
  -- 'percent': Porcentaje de descuento
  -- 'fixed': Monto fijo de descuento

  discount_value DECIMAL(12,2) NOT NULL,
  currency_code VARCHAR(3) DEFAULT 'MXN',  -- Solo para tipo 'fixed'

  -- Restricciones
  max_redemptions INTEGER,          -- Máximo de usos totales
  max_redemptions_per_tenant INTEGER DEFAULT 1,  -- Máximo por tenant
  redemptions_count INTEGER NOT NULL DEFAULT 0,

  -- Vigencia
  valid_from TIMESTAMP,
  valid_until TIMESTAMP,

  -- Aplicable a
  applicable_plans UUID[],  -- Array de plan_ids, NULL = todos

  -- Estado
  is_active BOOLEAN NOT NULL DEFAULT true,

  -- Auditoría
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID,

  CONSTRAINT chk_coupons_discount CHECK (
    (discount_type = 'percent' AND discount_value > 0 AND discount_value <= 100) OR
    (discount_type = 'fixed' AND discount_value > 0)
  ),
  CONSTRAINT chk_coupons_dates CHECK (valid_until IS NULL OR valid_until > valid_from)
);

-- Tabla: coupon_redemptions (Uso de cupones)
CREATE TABLE billing.coupon_redemptions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  coupon_id UUID NOT NULL REFERENCES billing.coupons(id),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  subscription_id UUID REFERENCES billing.subscriptions(id),

  -- Auditoría
  redeemed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  redeemed_by UUID,

  CONSTRAINT uq_coupon_redemptions UNIQUE (coupon_id, tenant_id)
);

-- Tabla: subscription_history (Historial de cambios de suscripción)
CREATE TABLE billing.subscription_history (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  subscription_id UUID NOT NULL REFERENCES billing.subscriptions(id) ON DELETE CASCADE,

  event_type VARCHAR(50) NOT NULL,
  -- 'created', 'upgraded', 'downgraded', 'renewed', 'cancelled',
  -- 'paused', 'resumed', 'payment_failed', 'payment_succeeded'

  previous_plan_id UUID REFERENCES billing.subscription_plans(id),
  new_plan_id UUID REFERENCES billing.subscription_plans(id),
  previous_status billing.subscription_status,
  new_status billing.subscription_status,

  -- Metadata adicional
  metadata JSONB DEFAULT '{}'::jsonb,
  notes TEXT,

  -- Auditoría
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID
);

-- =====================================================
-- ÍNDICES
-- =====================================================

-- subscription_plans
CREATE INDEX idx_plans_is_active ON billing.subscription_plans(is_active) WHERE is_active = true;
CREATE INDEX idx_plans_is_public ON billing.subscription_plans(is_public) WHERE is_public = true;

-- tenant_owners
CREATE INDEX idx_tenant_owners_tenant_id ON billing.tenant_owners(tenant_id);
CREATE INDEX idx_tenant_owners_user_id ON billing.tenant_owners(user_id);

-- subscriptions
CREATE INDEX idx_subscriptions_tenant_id ON billing.subscriptions(tenant_id);
CREATE INDEX idx_subscriptions_status ON billing.subscriptions(status);
CREATE INDEX idx_subscriptions_period_end ON billing.subscriptions(current_period_end);

-- payment_methods
CREATE INDEX idx_payment_methods_tenant_id ON billing.payment_methods(tenant_id);
CREATE INDEX idx_payment_methods_default ON billing.payment_methods(tenant_id, is_default) WHERE is_default = true;

-- invoices
CREATE INDEX idx_invoices_tenant_id ON billing.invoices(tenant_id);
CREATE INDEX idx_invoices_status ON billing.invoices(status);
CREATE INDEX idx_invoices_due_date ON billing.invoices(due_date);
CREATE INDEX idx_invoices_stripe_id ON billing.invoices(stripe_invoice_id);

-- payments
CREATE INDEX idx_payments_tenant_id ON billing.payments(tenant_id);
CREATE INDEX idx_payments_status ON billing.payments(status);
CREATE INDEX idx_payments_invoice_id ON billing.payments(invoice_id);

-- usage_records
CREATE INDEX idx_usage_records_tenant_id ON billing.usage_records(tenant_id);
CREATE INDEX idx_usage_records_period ON billing.usage_records(billing_period);
CREATE INDEX idx_usage_records_metric ON billing.usage_records(metric_type, billing_period);

-- coupons
CREATE INDEX idx_coupons_code ON billing.coupons(code);
CREATE INDEX idx_coupons_active ON billing.coupons(is_active) WHERE is_active = true;

-- subscription_history
CREATE INDEX idx_subscription_history_subscription ON billing.subscription_history(subscription_id);
CREATE INDEX idx_subscription_history_created ON billing.subscription_history(created_at);

-- =====================================================
-- TRIGGERS
-- =====================================================

-- Trigger updated_at para subscriptions
CREATE TRIGGER trg_subscriptions_updated_at
  BEFORE UPDATE ON billing.subscriptions
  FOR EACH ROW EXECUTE FUNCTION auth.update_updated_at_column();

-- Trigger updated_at para payment_methods
CREATE TRIGGER trg_payment_methods_updated_at
  BEFORE UPDATE ON billing.payment_methods
  FOR EACH ROW EXECUTE FUNCTION auth.update_updated_at_column();

-- Trigger updated_at para invoices
CREATE TRIGGER trg_invoices_updated_at
  BEFORE UPDATE ON billing.invoices
  FOR EACH ROW EXECUTE FUNCTION auth.update_updated_at_column();

-- Trigger updated_at para subscription_plans
CREATE TRIGGER trg_plans_updated_at
  BEFORE UPDATE ON billing.subscription_plans
  FOR EACH ROW EXECUTE FUNCTION auth.update_updated_at_column();

-- =====================================================
-- FUNCIONES
-- =====================================================

-- Función para obtener el plan actual de un tenant
CREATE OR REPLACE FUNCTION billing.get_tenant_plan(p_tenant_id UUID)
RETURNS TABLE(
  plan_code VARCHAR,
  plan_name VARCHAR,
  max_users INTEGER,
  max_companies INTEGER,
  features JSONB,
  subscription_status billing.subscription_status,
  days_until_renewal INTEGER
) AS $$
BEGIN
  RETURN QUERY
  SELECT
    sp.code,
    sp.name,
    sp.max_users,
    sp.max_companies,
    sp.features,
    s.status,
    EXTRACT(DAY FROM s.current_period_end - CURRENT_TIMESTAMP)::INTEGER
  FROM billing.subscriptions s
  JOIN billing.subscription_plans sp ON s.plan_id = sp.id
  WHERE s.tenant_id = p_tenant_id;
END;
$$ LANGUAGE plpgsql;

-- Función para verificar si tenant puede agregar más usuarios
CREATE OR REPLACE FUNCTION billing.can_add_user(p_tenant_id UUID)
RETURNS BOOLEAN AS $$
DECLARE
  v_max_users INTEGER;
  v_current_users INTEGER;
BEGIN
  -- Obtener límite del plan
  SELECT sp.max_users INTO v_max_users
  FROM billing.subscriptions s
  JOIN billing.subscription_plans sp ON s.plan_id = sp.id
  WHERE s.tenant_id = p_tenant_id AND s.status IN ('active', 'trialing');

  -- Si no hay límite (NULL), permitir
  IF v_max_users IS NULL THEN
    RETURN true;
  END IF;

  -- Contar usuarios actuales
  SELECT COUNT(*) INTO v_current_users
  FROM auth.users
  WHERE tenant_id = p_tenant_id AND deleted_at IS NULL;

  RETURN v_current_users < v_max_users;
END;
$$ LANGUAGE plpgsql;

-- Función para verificar si una feature está habilitada para el tenant
CREATE OR REPLACE FUNCTION billing.has_feature(p_tenant_id UUID, p_feature VARCHAR)
RETURNS BOOLEAN AS $$
DECLARE
  v_features JSONB;
BEGIN
  SELECT sp.features INTO v_features
  FROM billing.subscriptions s
  JOIN billing.subscription_plans sp ON s.plan_id = sp.id
  WHERE s.tenant_id = p_tenant_id AND s.status IN ('active', 'trialing');

  -- Si no hay plan o features, denegar
  IF v_features IS NULL THEN
    RETURN false;
  END IF;

  -- Verificar feature
  RETURN COALESCE((v_features ->> p_feature)::boolean, false);
END;
$$ LANGUAGE plpgsql;

-- =====================================================
-- DATOS INICIALES (Plans por defecto)
-- =====================================================

-- Plan Free/Trial
INSERT INTO billing.subscription_plans (code, name, description, price_monthly, price_yearly, max_users, max_companies, max_storage_gb, trial_days, is_default, sort_order, features)
VALUES (
  'free',
  'Free / Trial',
  'Plan gratuito para probar el sistema',
  0, 0,
  3, 1, 1, 14, true, 1,
  '{"inventory": true, "sales": true, "financial": false, "purchase": false, "crm": false, "projects": false, "reports_basic": true, "reports_advanced": false, "api_access": false}'::jsonb
);

-- Plan Básico
INSERT INTO billing.subscription_plans (code, name, description, price_monthly, price_yearly, max_users, max_companies, max_storage_gb, trial_days, sort_order, features)
VALUES (
  'basic',
  'Básico',
  'Ideal para pequeños negocios',
  499, 4990,
  5, 1, 5, 14, 2,
  '{"inventory": true, "sales": true, "financial": true, "purchase": true, "crm": false, "projects": false, "reports_basic": true, "reports_advanced": false, "api_access": false}'::jsonb
);

-- Plan Profesional
INSERT INTO billing.subscription_plans (code, name, description, price_monthly, price_yearly, max_users, max_companies, max_storage_gb, trial_days, sort_order, features)
VALUES (
  'professional',
  'Profesional',
  'Para empresas en crecimiento',
  999, 9990,
  15, 3, 20, 14, 3,
  '{"inventory": true, "sales": true, "financial": true, "purchase": true, "crm": true, "projects": true, "reports_basic": true, "reports_advanced": true, "api_access": true}'::jsonb
);

-- Plan Enterprise
INSERT INTO billing.subscription_plans (code, name, description, price_monthly, price_yearly, max_users, max_companies, max_storage_gb, trial_days, sort_order, features)
VALUES (
  'enterprise',
  'Enterprise',
  'Solución completa para grandes empresas',
  2499, 24990,
  NULL, NULL, 100, 30, 4,  -- NULL = ilimitado
  '{"inventory": true, "sales": true, "financial": true, "purchase": true, "crm": true, "projects": true, "reports_basic": true, "reports_advanced": true, "api_access": true, "white_label": true, "priority_support": true, "custom_integrations": true}'::jsonb
);

-- Plan Single-Tenant (para instalaciones on-premise)
INSERT INTO billing.subscription_plans (code, name, description, price_monthly, price_yearly, max_users, max_companies, max_storage_gb, trial_days, is_public, sort_order, features)
VALUES (
  'single_tenant',
  'Single Tenant / On-Premise',
  'Instalación dedicada sin restricciones',
  0, 0,
  NULL, NULL, NULL, 0, false, 99,  -- No público, solo asignación manual
  '{"inventory": true, "sales": true, "financial": true, "purchase": true, "crm": true, "projects": true, "reports_basic": true, "reports_advanced": true, "api_access": true, "white_label": true, "priority_support": true, "custom_integrations": true, "unlimited": true}'::jsonb
);

-- =====================================================
-- COMENTARIOS
-- =====================================================

COMMENT ON SCHEMA billing IS 'Schema para gestión de suscripciones SaaS, planes, pagos y facturación';

COMMENT ON TABLE billing.subscription_plans IS 'Planes de suscripción disponibles (global, no por tenant)';
COMMENT ON TABLE billing.tenant_owners IS 'Propietarios/administradores de facturación de cada tenant';
COMMENT ON TABLE billing.subscriptions IS 'Suscripciones activas de cada tenant';
COMMENT ON TABLE billing.payment_methods IS 'Métodos de pago registrados por tenant';
COMMENT ON TABLE billing.invoices IS 'Facturas de suscripción';
COMMENT ON TABLE billing.invoice_lines IS 'Líneas de detalle de facturas';
COMMENT ON TABLE billing.payments IS 'Pagos recibidos';
COMMENT ON TABLE billing.usage_records IS 'Registros de uso para billing por consumo';
COMMENT ON TABLE billing.coupons IS 'Cupones de descuento';
COMMENT ON TABLE billing.coupon_redemptions IS 'Registro de cupones usados';
COMMENT ON TABLE billing.subscription_history IS 'Historial de cambios de suscripción';

COMMENT ON FUNCTION billing.get_tenant_plan IS 'Obtiene información del plan actual de un tenant';
COMMENT ON FUNCTION billing.can_add_user IS 'Verifica si el tenant puede agregar más usuarios según su plan';
COMMENT ON FUNCTION billing.has_feature IS 'Verifica si una feature está habilitada para el tenant';
