-- =============================================================================
-- MICHANGARRITO - 13 REFERRALS
-- =============================================================================
-- Programa de referidos: codigos, referidos y recompensas
-- =============================================================================

-- Codigos de referido
CREATE TABLE IF NOT EXISTS subscriptions.referral_codes (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,

    code VARCHAR(20) UNIQUE NOT NULL,

    active BOOLEAN DEFAULT true,
    uses_count INTEGER DEFAULT 0,

    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_referral_codes_tenant ON subscriptions.referral_codes(tenant_id);
CREATE INDEX idx_referral_codes_code ON subscriptions.referral_codes(code);

CREATE TRIGGER update_referral_codes_updated_at
    BEFORE UPDATE ON subscriptions.referral_codes
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

-- Referidos
CREATE TABLE IF NOT EXISTS subscriptions.referrals (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    referrer_tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
    referred_tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,

    code_used VARCHAR(20) NOT NULL,

    status VARCHAR(20) DEFAULT 'pending',
    -- pending: referido registrado, no ha pagado
    -- converted: referido pago primer mes
    -- rewarded: recompensa aplicada al referidor
    -- expired: referido no pago en tiempo (30 dias)

    referred_discount_applied BOOLEAN DEFAULT false,
    referrer_reward_applied BOOLEAN DEFAULT false,

    converted_at TIMESTAMPTZ,
    reward_applied_at TIMESTAMPTZ,
    expires_at TIMESTAMPTZ,

    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),

    UNIQUE(referred_tenant_id)
);

CREATE INDEX idx_referrals_referrer ON subscriptions.referrals(referrer_tenant_id);
CREATE INDEX idx_referrals_referred ON subscriptions.referrals(referred_tenant_id);
CREATE INDEX idx_referrals_status ON subscriptions.referrals(status);

CREATE TRIGGER update_referrals_updated_at
    BEFORE UPDATE ON subscriptions.referrals
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

-- Recompensas de referidos
CREATE TABLE IF NOT EXISTS subscriptions.referral_rewards (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
    referral_id UUID NOT NULL REFERENCES subscriptions.referrals(id) ON DELETE CASCADE,

    type VARCHAR(20) NOT NULL DEFAULT 'free_month',
    -- free_month: mes gratis de suscripcion
    -- discount: descuento porcentual

    months_earned INTEGER DEFAULT 0,
    months_used INTEGER DEFAULT 0,
    discount_percent INTEGER DEFAULT 0,

    expires_at TIMESTAMPTZ,

    status VARCHAR(20) DEFAULT 'available',
    -- available: disponible para usar
    -- used: ya se uso
    -- expired: expiro sin usarse

    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_referral_rewards_tenant ON subscriptions.referral_rewards(tenant_id);
CREATE INDEX idx_referral_rewards_status ON subscriptions.referral_rewards(status);

CREATE TRIGGER update_referral_rewards_updated_at
    BEFORE UPDATE ON subscriptions.referral_rewards
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

-- Funcion para generar codigo de referido unico
CREATE OR REPLACE FUNCTION generate_referral_code(prefix TEXT DEFAULT 'MCH')
RETURNS TEXT AS $$
DECLARE
    new_code TEXT;
    code_exists BOOLEAN;
BEGIN
    LOOP
        -- Generar codigo alfanumerico de 6 caracteres
        new_code := prefix || '-' || upper(substr(md5(random()::text), 1, 6));

        -- Verificar si ya existe
        SELECT EXISTS(
            SELECT 1 FROM subscriptions.referral_codes WHERE code = new_code
        ) INTO code_exists;

        -- Si no existe, salir del loop
        EXIT WHEN NOT code_exists;
    END LOOP;

    RETURN new_code;
END;
$$ LANGUAGE plpgsql;

-- Funcion para obtener estadisticas de referidos
CREATE OR REPLACE FUNCTION get_referral_stats(p_tenant_id UUID)
RETURNS TABLE (
    total_invited INTEGER,
    total_converted INTEGER,
    total_pending INTEGER,
    total_expired INTEGER,
    months_earned INTEGER,
    months_available INTEGER
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        COUNT(*)::INTEGER as total_invited,
        COUNT(*) FILTER (WHERE r.status IN ('converted', 'rewarded'))::INTEGER as total_converted,
        COUNT(*) FILTER (WHERE r.status = 'pending')::INTEGER as total_pending,
        COUNT(*) FILTER (WHERE r.status = 'expired')::INTEGER as total_expired,
        COALESCE(SUM(rw.months_earned), 0)::INTEGER as months_earned,
        COALESCE(SUM(rw.months_earned - rw.months_used) FILTER (WHERE rw.status = 'available'), 0)::INTEGER as months_available
    FROM subscriptions.referrals r
    LEFT JOIN subscriptions.referral_rewards rw ON rw.referral_id = r.id AND rw.tenant_id = p_tenant_id
    WHERE r.referrer_tenant_id = p_tenant_id;
END;
$$ LANGUAGE plpgsql;
